最近在和几个java高手一起做几个javaIDE,不过是简略版本的,
我主要负责的是将编译程序的结果输出到我们的“控制台”
(其实是一个JTEXTPANE)上,其中遇到了一些麻烦,因为毕竟我的java很菜,
所以了,到处查资料,终于了解到了利用重定向System.out 和
System.err到JTextPane就可以了。
成功后心情很是爽啊,呵呵,现在将这个测试的代码贴上来和大家共享。
import java.awt.*;
import java.io.*;
import javax.swing.*;
import javax.swing.text.*;
/**
*
*/
public class ConsolePane extends JScrollPane {
private JTextPane textPane = new JTextPane();
private static ConsolePane console = null;
public static synchronized ConsolePane getInstance() {
if (console == null) {
console = new ConsolePane();
}
return console;
}
private ConsolePane() {
setViewportView(textPane);
// Set up System.out
PrintStream mySystemOut = new MyPrintStream(System.out, Color.BLACK);
System.setOut(mySystemOut);
// Set up System.err
PrintStream mySystemErr = new MyPrintStream(System.err, Color.RED);
System.setErr(mySystemErr);
textPane.setEditable(true);
setPreferredSize(new Dimension(640, 120));
}
/**
* Returns the number of lines in the document.
*/
private final int getLineCount() {
return textPane.getDocument().getDefaultRootElement().getElementCount();
}
/**
* Returns the start offset of the specified line.
* @param line The line
* @return The start offset of the specified line, or -1 if the line is
* invalid
*/
private int getLineStartOffset(int line) {
Element lineElement = textPane.getDocument().getDefaultRootElement()
.getElement(line);
if (lineElement == null)
return -1;
else
return lineElement.getStartOffset();
}
/**
* 清除超过行数时前面多出行的字符
*/
private void replaceRange(String str, int start, int end) {
if (end < start) {
throw new IllegalArgumentException("end before start");
}
Document doc = textPane.getDocument();
if (doc != null) {
try {
if (doc instanceof AbstractDocument) {
((AbstractDocument) doc).replace(start, end - start, str,
null);
} else {
doc.remove(start, end - start);
doc.insertString(start, str, null);
}
} catch (BadLocationException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
}
class MyPrintStream extends PrintStream {
private Color foreground; //输出时所用字体颜色
/**
* 构造自己的 PrintStream
* @param out 可传入 System.out 或 System.err, 实际不起作用
* @param foreground 显示字体颜色
*/
MyPrintStream(OutputStream out,Color foreground) {
super(out,true); //使用自动刷新
this.foreground = foreground;
}
/**
* 在这里重截,所有的打印方法都要调用最底一层的方法
*/
public void write(byte[] buf, int off, int len) {
final String message = new String(buf, off, len);
/** SWING非界面线程访问组件的方式 */
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
StyledDocument doc = (StyledDocument) textPane
.getDocument();
// Create a style object and then set the style
// attributes
Style style = doc.addStyle("StyleName", null);
// Foreground color
StyleConstants.setForeground(style, foreground);
doc.insertString(doc.getLength(), message, style);
} catch (BadLocationException e) {
// e.printStackTrace();
}
// Make sure the last line is always visible
textPane.setCaretPosition(textPane.getDocument()
.getLength());
// Keep the text area down to a certain line count
int idealLine = 150;
int maxExcess = 50;
int excess = getLineCount() - idealLine;
if (excess >= maxExcess) {
replaceRange("", 0, getLineStartOffset(excess));
}
}
});
}
}
} |
把 System.out 和 System.err 重定向到 JTextArea 的做法在网上能找到不少,由于 JTextArea 不能用不同的字体分别显示内容。但我还是希望能象 Eclipse 控制台那样,标准输出为黑色,错误信息为红色,于是选择了 JTextPane 作为输出目的地。线程之间通信息用到了 PipedInputStream 、PipedOutputStream 和 SwingUtilities.invokeLater(new Runnable())。
自定义了一个 JScrollPane,类名为 ConsolePane,写成的单例类;使用时只需要在你的面板上加上 ConsolePane组件,例如:getContentPane().add(ConsolePane.getInstance(), BorderLayout.CENTER);
阅读(1453) | 评论(0) | 转发(0) |