从可运行线程追加时 JTextArea 空白

JTextArea blank when appending from a runnable thread

我是 Swing 新手,正在开发桌面应用程序。该应用程序的一部分有一个后台进程 运行 一个 .exe,然后将终端的输出读入动态创建的 JtextArea。我将此输出附加到 JtextArea(线程安全)。我可以在 PrintLn 中看到输出,但在 JTextArea 中看不到。事实上,JTextRea 是冻结的并且是空白的。我怀疑与 revalidate 和 repaint 有关,但我只是想知道将它们放在哪里?这是完成这项工作的代码。欢迎任何帮助或建议。

progressWindow = new JFrame("Please wait ...");

                FlowLayout defFileFlow = new FlowLayout();
               progressWindow.setLayout(defFileFlow);
                defFileFlow.setAlignment(FlowLayout.TRAILING);
                progressWindow.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                progressWindow.setSize(550,680);

                progressPane = new JTextArea(30, 80);
                DefaultCaret caret = (DefaultCaret)progressPane.getCaret();
                caret.setUpdatePolicy(DefaultCaret.OUT_BOTTOM);

               progressPane.setLayout(new BorderLayout(500, 500));
               progressPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

                progressPane.setFont(new Font("Monospaced", 0, 12));
                progressPane.setText("Please wait while we crunch some numbers .." + "\n");
                JScrollPane scroller = new JScrollPane(progressPane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

               progressWindow.add(scroller);
               scroller.setBounds(0, 0, 500, 500);

                JButton cancelButton = new JButton("Cancel Analysis");
                progressWindow.add(cancelButton);
                progressWindow.setComponentOrientation(ComponentOrientation.UNKNOWN);
                progressWindow.setVisible(true);
                progressWindow.setAlwaysOnTop(true);

                Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
                progressWindow.setLocation(dim.width/2-progressWindow.getSize().width/2, dim.height/2-progressWindow.getSize().height/2);


            try {         
                   copyExecutable(defFilePath, selectedModel);
                   Process p=Runtime.getRuntime().exec("cmd /c dir && cd " + defFilePath + " && dir && "
                            + defFileName); 
                   Thread runCMD = new Thread(new Runnable(){
                       public void run() {
                           System.out.println("Inside the thread");
                           try{
                                InputStreamReader isr = new InputStreamReader(p.getInputStream());
                                BufferedReader br = new BufferedReader(isr);
                                String line=null;  // UI magic should run in here @adityapona
                                while ( (line = br.readLine()) != null){
                                    System.out.println("MIXWILD:" + line);
                                    progressPane.append("MIXWILD:" + line + "\n");

progressPane.setCaretPosition(progressPane.getDocument().getLength());
                                }
                                } catch (IOException ioe)
                                  {
                                    ioe.printStackTrace();  
                                  }                       
                       }
                   });
                  runCMD.start();

重要 当线程运行时 window 成功关闭并且 returns 退出值为 0。

Process p=Runtime.getRuntime().exec("...);
Thread runCMD = new Thread(new Runnable(){

进程正在 运行 Event Dispatch Thread (EDT) 上,这会阻止 GUI 响应事件和重新绘制自身。

进程本身应该从线程中启动。 (即尝试将 Process 语句从 Thread 外部移动到 运行() 方法内部,以便 Process 在单独的线程上执行,而不是 EDT 线程。)

阅读 Swing 教程中有关 Swing 并发的部分,了解更多信息。您可能需要考虑使用专为此类处理设计的 SwingWorker。它允许您在 运行ning 任务和 "publish" 结果可用时调用它们。这是比仅使用线程更好的解决方案,因为 "publish" 进程将确保 "append" 在 EDT 上执行。

编辑:

progressPane.setLayout(new BorderLayout(500, 500));

为什么要尝试为文本区域提供布局管理器?怀疑它会导致问题,但绝对不需要也不应该使用。

progressWindow.setComponentOrientation(ComponentOrientation.UNKNOWN);

不用玩方向

scroller.setBounds(0, 0, 500, 500);

不要玩越界。设置组件的 size/location 是布局管理器的工作。