如何从没有swing组件init的线程将数据记录到JTextArea(或JTextPane)?

时间:2012-05-04 13:26:47

标签: java swing logging jtextarea jtextpane

我有一个处理一些数据的GUI应用程序,它将文本行转换为对象。创建的每个对象都显示在JTextPane或JTextArea上。例如:

第1行创建了827401830 第2行创建了827401831

因此用户通知该过程。

在幕后,有一个在后台运行的线程并完成所有工作。问题是该线程的一个字段是JTextArea。它看起来像这样:

public class ConsumerThread implements Runnable 
{
    private ArrayBlockingQueue<TicketExchangeLine> queue;
    private JTextArea textArea; 

public ExchConsumerThread(ArrayBlockingQueue<TicketExchangeLine> queue, JTextArea textArea) 
{
    this.queue = queue;
    this.textArea = textArea; 
}

public void run() 
{
    try
    {       
        while (true)
        {               
            // check if end of file from producer POV
            if (queue.peek()!=null && ...)
                break;

            MyObject obj = queue.take();

            try{
                //do the process here
                textArea.append("here comes the output for the user..."+obj.getID);

            }catch(Exception nfe)
            {
                //Oops  
            } 
        }

        textArea.append("\nDone!");

    }catch (InterruptedException e)
    {
        // Oops
    }catch(Exception exp)
    {
        exp.printStackTrace();
    }
}

}

所以上面的代码工作正常并完成工作,但有时我使用的这个线程不是来自GUI,然后我无缘无故地实例化JTextArea;更糟糕的是,我必须在system.out一切看到这个过程。

问题:如何在不使用线程中的Swing组件的情况下将所有“已处理数据”记录到JTextArea(或有时是JTextPane)?

谢谢!

4 个答案:

答案 0 :(得分:2)

不是传递JTextArea,而是传递OutputStream(例如PrintStream)作为参数。这提供了足够的灵活性:

  • 您的线程只是写入输出流
  • 如果您希望输出显示在JTextArea中,则传递输出流,该输出流将输出附加到JTextArea。写入文本区域应该在EDT上进行,但输出流会处理这个问题。你的线程不知道这个
  • 如果您想将输出传输到System.out,只需将System.out直接作为参数传递

答案 1 :(得分:1)

大多数Swing图形组件被拆分为图形表示(View)和显示数据的抽象表示(Model)。 JTextAreaJTextPane是使用Document实例作为模型的图形组件。

因此,您可以引用文档,然后调用JTextArea,而不是引用textArea.append并调用document.insertString。然后,如果您需要实例化JTextArea,请使用JTextArea的构造函数,该构造函数将Document作为参数(或使用其setDocument方法)。

此外,Swing不是线程安全的,并且每个可能影响Swing组件的方法调用都应该在EDT(AWT的调度线程)中发生。要在EDT上注入一些代码,请使用SwingUtilities.invokeLater

答案 2 :(得分:0)

不确定这是否是您要实现的目标,但是使用您当前的代码,您可以更改EDT上的JTextArea,如下所示:

final MyObject obj = queue.take();
try {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            textArea.append("here comes the output for the user..." + obj.getID);
        }
    });
}

答案 3 :(得分:0)

您似乎已经找到了答案,但我认为这是解决您问题的优雅而灵活的解决方案:

Sending messages to a swing JTextArea from different places