在GUI面板中创buildJava控制台

如何在GUI面板中创buildJava控制台的实例?

这是一个function正常的课程。 你可以把这个实例安装到系统中,然后使用:

PrintStream con=new PrintStream(new TextAreaOutputStream(...)); System.setOut(con); System.setErr(con); 

更新2014-02-19 :使用EventQueue.invokeLater()来避免GUI线程问题,这些问题很less会与原始问题一起出现。

更新2014-02-27 :更好的实施

更新2014年3月25日 :正确logging和删除文本区域中的行在run()方法中,以避免添加和删除之间的竞争条件,如果控制台被填充输出。 最终结果对我来说似乎也更清洁。

 import java.awt.*; import java.io.*; import java.util.*; import java.util.List; import javax.swing.*; public class TextAreaOutputStream extends OutputStream { // ************************************************************************************************* // INSTANCE MEMBERS // ************************************************************************************************* private byte[] oneByte; // array for write(int val); private Appender appender; // most recent action public TextAreaOutputStream(JTextArea txtara) { this(txtara,1000); } public TextAreaOutputStream(JTextArea txtara, int maxlin) { if(maxlin<1) { throw new IllegalArgumentException("TextAreaOutputStream maximum lines must be positive (value="+maxlin+")"); } oneByte=new byte[1]; appender=new Appender(txtara,maxlin); } /** Clear the current console text area. */ public synchronized void clear() { if(appender!=null) { appender.clear(); } } public synchronized void close() { appender=null; } public synchronized void flush() { } public synchronized void write(int val) { oneByte[0]=(byte)val; write(oneByte,0,1); } public synchronized void write(byte[] ba) { write(ba,0,ba.length); } public synchronized void write(byte[] ba,int str,int len) { if(appender!=null) { appender.append(bytesToString(ba,str,len)); } } @edu.umd.cs.findbugs.annotations.SuppressWarnings("DM_DEFAULT_ENCODING") static private String bytesToString(byte[] ba, int str, int len) { try { return new String(ba,str,len,"UTF-8"); } catch(UnsupportedEncodingException thr) { return new String(ba,str,len); } // all JVMs are required to support UTF-8 } // ************************************************************************************************* // STATIC MEMBERS // ************************************************************************************************* static class Appender implements Runnable { private final JTextArea textArea; private final int maxLines; // maximum lines allowed in text area private final LinkedList<Integer> lengths; // length of lines within text area private final List<String> values; // values waiting to be appended private int curLength; // length of current line private boolean clear; private boolean queue; Appender(JTextArea txtara, int maxlin) { textArea =txtara; maxLines =maxlin; lengths =new LinkedList<Integer>(); values =new ArrayList<String>(); curLength=0; clear =false; queue =true; } synchronized void append(String val) { values.add(val); if(queue) { queue=false; EventQueue.invokeLater(this); } } synchronized void clear() { clear=true; curLength=0; lengths.clear(); values.clear(); if(queue) { queue=false; EventQueue.invokeLater(this); } } // MUST BE THE ONLY METHOD THAT TOUCHES textArea! public synchronized void run() { if(clear) { textArea.setText(""); } for(String val: values) { curLength+=val.length(); if(val.endsWith(EOL1) || val.endsWith(EOL2)) { if(lengths.size()>=maxLines) { textArea.replaceRange("",0,lengths.removeFirst()); } lengths.addLast(curLength); curLength=0; } textArea.append(val); } values.clear(); clear =false; queue =true; } static private final String EOL1="\n"; static private final String EOL2=System.getProperty("line.separator",EOL1); } } /* END PUBLIC CLASS */ 

下面是它的一个截图:

在这里输入图像描述

@Sofware猴子:

有用! 🙂

 import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; public class Main{ public static void main( String [] args ) throws InterruptedException { JFrame frame = new JFrame(); frame.add( new JLabel(" Outout" ), BorderLayout.NORTH ); JTextArea ta = new JTextArea(); TextAreaOutputStream taos = new TextAreaOutputStream( ta, 60 ); PrintStream ps = new PrintStream( taos ); System.setOut( ps ); System.setErr( ps ); frame.add( new JScrollPane( ta ) ); frame.pack(); frame.setVisible( true ); frame.setSize(800,600); for( int i = 0 ; i < 100 ; i++ ) { System.out.println( i ); Thread.sleep( 500 ); } } } 

我知道这是一个古老的线索,但是我发现它的同时,试图找出一个好办法,这意味着其他人也可能会。

这是一个(可能)更干净的方式做什么软件猴子张贴:

 import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import javax.swing.JTextArea; /** * Represents a console viewable through a <code>JTextArea</code>. * * <p> * Implementation: * <code> * System.setOut(new PrintStream(new Console( ... ))); * </code> * </p> * * @author Derive McNeill * */ public class Console extends OutputStream { /** * Represents the data written to the stream. */ ArrayList <Byte> data = new ArrayList <Byte> (); /** * Represents the text area that will be showing the written data. */ private JTextArea output; /** * Creates a console context. * @param output * The text area to output the consoles text. */ public Console(JTextArea output) { this.output = output; } /** * Called when data has been written to the console. */ private void fireDataWritten() { // First we loop through our written data counting the lines. int lines = 0; for (int i = 0; i < data.size(); i++) { byte b = data.get(i); // Specifically we look for 10 which represents "\n". if (b == 10) { lines++; } // If the line count exceeds 250 we remove older lines. if (lines >= 250) { data = (ArrayList<Byte>) data.subList(i, data.size()); } } // We then create a string builder to append our text data. StringBuilder bldr = new StringBuilder(); // We loop through the text data appending it to the string builder. for (byte b : data) { bldr.append((char) b); } // Finally we set the outputs text to our built string. output.setText(bldr.toString()); } @Override public void write(int i) throws IOException { // Append the piece of data to our array of data. data.add((byte) i); // Indicate that data has just been written. fireDataWritten(); } } 

ByteArrayOutputStream可以用来省略缓冲的东西。

 private void redirectConsoleTo(final JTextArea textarea) { PrintStream out = new PrintStream(new ByteArrayOutputStream() { public synchronized void flush() throws IOException { textarea.setText(toString()); } }, true); System.setErr(out); System.setOut(out); } 

您可以将ByteArrayOutputStream#reset()绑定到某个button,而不是限制行号。

 private void redirectConsoleWithClearButton(final JTextArea textarea, JButton clearButton) { final ByteArrayOutputStream bytes = new ByteArrayOutputStream() { public synchronized void flush() throws IOException { textarea.setText(toString()); } }; clearButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { bytes.reset(); } }); PrintStream out = new PrintStream(bytes, true); System.setErr(out); System.setOut(out); } 

我最近使用了Lawrence Dol在我的一个项目中提供的优秀代码 。

但是,在我的情况下,代码消耗了太多的内存。 我设法通过用JLabelreplaceJTextarea来大大减less内存消耗。

我的记忆保存search显示, JTextarea内部代码倾向于保存实际文本发送太多的时间。 因此,所有这些文字都不能被垃圾收集。

这里是初始代码的灵活版本(通过锁代替线程同步)。

JComponentOutputStream.java

 import java.awt.EventQueue; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import javax.swing.JComponent; public class JComponentOutputStream extends OutputStream { // ************************************************************************************************* // INSTANCE MEMBERS // ************************************************************************************************* private byte[] oneByte; // array for write(int val); private Appender appender; // most recent action private Lock jcosLock = new ReentrantLock(); public JComponentOutputStream(JComponent txtara, JComponentHandler handler) { this(txtara, 1000, handler); } public JComponentOutputStream(JComponent txtara, int maxlin, JComponentHandler handler) { if (maxlin < 1) { throw new IllegalArgumentException("JComponentOutputStream maximum lines must be positive (value=" + maxlin + ")"); } oneByte = new byte[1]; appender = new Appender(txtara, maxlin, handler); } /** Clear the current console text area. */ public void clear() { jcosLock.lock(); try { if (appender != null) { appender.clear(); } } finally { jcosLock.unlock(); } } public void close() { jcosLock.lock(); try { appender = null; } finally { jcosLock.unlock(); } } public void flush() { // sstosLock.lock(); // try { // // TODO: Add necessary code here... // } finally { // sstosLock.unlock(); // } } public void write(int val) { jcosLock.lock(); try { oneByte[0] = (byte) val; write(oneByte, 0, 1); } finally { jcosLock.unlock(); } } public void write(byte[] ba) { jcosLock.lock(); try { write(ba, 0, ba.length); } finally { jcosLock.unlock(); } } public void write(byte[] ba, int str, int len) { jcosLock.lock(); try { if (appender != null) { appender.append(bytesToString(ba, str, len)); } } finally { jcosLock.unlock(); } } static private String bytesToString(byte[] ba, int str, int len) { try { return new String(ba, str, len, "UTF-8"); } catch (UnsupportedEncodingException thr) { return new String(ba, str, len); } // all JVMs are required to support UTF-8 } // ************************************************************************************************* // STATIC MEMBERS // ************************************************************************************************* static class Appender implements Runnable { private final JComponent swingComponent; private final int maxLines; // maximum lines allowed in text area private final LinkedList<Integer> lengths; // length of lines within // text area private final List<String> values; // values waiting to be appended private int curLength; // length of current line private boolean clear; private boolean queue; private Lock appenderLock; private JComponentHandler handler; Appender(JComponent cpt, int maxlin, JComponentHandler hndlr) { appenderLock = new ReentrantLock(); swingComponent = cpt; maxLines = maxlin; lengths = new LinkedList<Integer>(); values = new ArrayList<String>(); curLength = 0; clear = false; queue = true; handler = hndlr; } void append(String val) { appenderLock.lock(); try { values.add(val); if (queue) { queue = false; EventQueue.invokeLater(this); } } finally { appenderLock.unlock(); } } void clear() { appenderLock.lock(); try { clear = true; curLength = 0; lengths.clear(); values.clear(); if (queue) { queue = false; EventQueue.invokeLater(this); } } finally { appenderLock.unlock(); } } // MUST BE THE ONLY METHOD THAT TOUCHES the JComponent! public void run() { appenderLock.lock(); try { if (clear) { handler.setText(swingComponent, ""); } for (String val : values) { curLength += val.length(); if (val.endsWith(EOL1) || val.endsWith(EOL2)) { if (lengths.size() >= maxLines) { handler.replaceRange(swingComponent, "", 0, lengths.removeFirst()); } lengths.addLast(curLength); curLength = 0; } handler.append(swingComponent, val); } values.clear(); clear = false; queue = true; } finally { appenderLock.unlock(); } } static private final String EOL1 = "\n"; static private final String EOL2 = System.getProperty("line.separator", EOL1); } public interface JComponentHandler { void setText(JComponent swingComponent, String text); void replaceRange(JComponent swingComponent, String text, int start, int end); void append(JComponent swingComponent, String text); } } /* END PUBLIC CLASS */ 

示例用法

 JLabel console = new JLabel(); JComponentOutputStream consoleOutputStream = new JComponentOutputStream(console, new JComponentHandler() { private StringBuilder sb = new StringBuilder(); @Override public void setText(JComponent swingComponent, String text) { sb.delete(0, sb.length()); append(swingComponent, text); } @Override public void replaceRange(JComponent swingComponent, String text, int start, int end) { sb.replace(start, end, text); redrawTextOf(swingComponent); } @Override public void append(JComponent swingComponent, String text) { sb.append(text); redrawTextOf(swingComponent); } private void redrawTextOf(JComponent swingComponent) { ((JLabel)swingComponent).setText("<html><pre>" + sb.toString() + "</pre></html>"); } }); PrintStream con = new PrintStream(consoleOutputStream); System.setOut(con); System.setErr(con); // Optional: add a scrollpane around the console for having scrolling bars JScrollPane sp = new JScrollPane( // console, // ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, // ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED // ); myPanel.add(sp);