Java System.out.println到JTextArea
编辑:我编辑了这篇文章来澄清我的问题,现在我自己有了更多的理解 正如标题所说,我基本上是在执行应用程序任务的同时,试图将控制台输出到GUI中的Java System.out.println到JTextArea,java,swing,user-interface,jtextarea,Java,Swing,User Interface,Jtextarea,编辑:我编辑了这篇文章来澄清我的问题,现在我自己有了更多的理解 正如标题所说,我基本上是在执行应用程序任务的同时,试图将控制台输出到GUI中的JTextArea 以下是我目前正在做的事情: public class TextAreaOutputStream extends OutputStream { private final JTextArea textArea; private final StringBuilder sb = new StringBuilder();
JTextArea
以下是我目前正在做的事情:
public class TextAreaOutputStream extends OutputStream
{
private final JTextArea textArea;
private final StringBuilder sb = new StringBuilder();
public TextAreaOutputStream(final JTextArea textArea)
{
this.textArea = textArea;
}
@Override
public void flush()
{
}
@Override
public void close()
{
}
@Override
public void write(int b) throws IOException
{
if (b == '\r')
return;
if (b == '\n')
{
final String text = sb.toString() + "\n";
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
textArea.append(text);
}
});
sb.setLength(0);
}
sb.append((char) b);
}
}
上述操作将成功地将System.out
重新定向到上面的我的输出流,从而将事件发送到事件队列
,以更新我的GUI(JTextArea
)
问题是:
当前使用的invokeLater()
将如文档中所述:
使runnable在EventQueue的调度线程中调用其run方法。这将在处理所有未决事件后发生。
因此,我实际上想做的是在处理EventQueue中的所有其他内容之前,对GUI执行更新(调用run()
)
是否可以将事件本质上注入到我的EventQueue中?或者有人能给我指一本关于这个领域的不错的教程吗
谢谢,您可能需要使用
PipedOutputStream
。。。请参见以下问题的答案:
基本上,它将
System.out
重定向到一个缓冲区,程序可以从中读取用System.out
打印的输出。这被称为管道以下示例创建带有文本区域的框架,并将System.out重定向到该框架:
import java.awt.BorderLayout;
import java.awt.Container;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class JTextAreaOutputStream extends OutputStream
{
private final JTextArea destination;
public JTextAreaOutputStream (JTextArea destination)
{
if (destination == null)
throw new IllegalArgumentException ("Destination is null");
this.destination = destination;
}
@Override
public void write(byte[] buffer, int offset, int length) throws IOException
{
final String text = new String (buffer, offset, length);
SwingUtilities.invokeLater(new Runnable ()
{
@Override
public void run()
{
destination.append (text);
}
});
}
@Override
public void write(int b) throws IOException
{
write (new byte [] {(byte)b}, 0, 1);
}
public static void main (String[] args) throws Exception
{
JTextArea textArea = new JTextArea (25, 80);
textArea.setEditable (false);
JFrame frame = new JFrame ("stdout");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
Container contentPane = frame.getContentPane ();
contentPane.setLayout (new BorderLayout ());
contentPane.add (
new JScrollPane (
textArea,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED),
BorderLayout.CENTER);
frame.pack ();
frame.setVisible (true);
JTextAreaOutputStream out = new JTextAreaOutputStream (textArea);
System.setOut (new PrintStream (out));
while (true)
{
System.out.println ("Current time: " + System.currentTimeMillis ());
Thread.sleep (1000L);
}
}
}
你的错误一定在别的地方,你还没有告诉我们。这是一个非常简单的演示,它的代码与您的代码几乎相同(我只修复了一些小问题):
如果您想在文本区域中看到滚动效果,则可以将新文本放在开头,而不是附加输出。
例如:
我发现最好的方法是非常简单,而且似乎效果很好。我已经用了很多年了,没有任何问题
JTextArea output = new JTextArea();
PrintStream out = new PrintStream(new OutputStream() {
@Override
public void write(int b) throws IOException {
output.append(""+(char)(b & 0xFF));
}
});
System.setOut(out);
System.out.println("TEST");
嗯,我的方法有什么问题?我在这里看到的是你刚刚重新创建了我的解决方案?您能指出它在哪里解决了我的问题吗?在上睡觉没有什么错,但应该在EDT上构建GUI组件。您的方法有几个小问题,即每个'\n'
输出两次,但不会导致您描述的问题。您确定!“.equals(targetFile.getText())
和checkBox.isSelected()
都是真的吗?”上述解决方案的工作原理是,我将sysout带到我的JTextArea,但是当我试图在actionPerformed()中执行此操作时,我没有得到任何输出。“您确定通过了所有这些if吗?”?一个System.out
调用会起作用,而另一个调用会失败,这是没有充分的理由的。问题是我自己在invokeLater()
上的愚蠢和误解。我的解决方案正在工作,但不是我所希望的,即,我的GUI在EventQueue
中的所有其他内容处理完毕后才会更新,这就是我上面代码片段中的…
。这不是我想要的。@buymypies顺便说一句,JTextArea.append
是线程安全的,所以没有必要将它包装在invokeLater()
中。请查看我对问题的编辑,希望我已经清楚地说明了我要做什么。@buymypies 1)没有必要将JTextArea.append
包装在invokeLater()
中。2) 如果您正在考虑对EventQueue上的事件重新排序,请忘记它(这并不难做到):这只意味着您在某个地方有一个错误的设计。如果您需要执行冗长的操作,请不要在EDT上执行,而是使用SwingWorker。
HttpURLConnection con = (HttpURLConnection) (new URL(url[0]).openConnection());
con.setInstanceFollowRedirects(false);
con.connect();
int responseCode = con.getResponseCode();
String location = con.getHeaderField("Location");
textArea.setText(url[0] +"," +responseCode+"," +location+"\n"+textArea.getText()); //new text is prefixed to the existing text
textArea.update(textArea.getGraphics());
JTextArea output = new JTextArea();
PrintStream out = new PrintStream(new OutputStream() {
@Override
public void write(int b) throws IOException {
output.append(""+(char)(b & 0xFF));
}
});
System.setOut(out);
System.out.println("TEST");