【问题标题】:Show / update components before process finished在流程完成之前显示/更新组件
【发布时间】:2013-12-06 15:39:16
【问题描述】:

我目前有一个带有 swing gui 的 java 程序,它允许用户选择各种文件(xsl-fo 和 xml)并使用 Render X 生成 PDF。我尝试了一段时间让一个弹出的 JFrame 在按钮时出现被按下,然后会显示一个进度条或标签以让用户了解进度。但是,当实例化一个新框架时,它会显示为黑色,或者没有组件,然后在进程完成后显示。

private void RunButtonActionPerformed(java.awt.event.ActionEvent evt) {

    ExecutorService executor = Executors.newFixedThreadPool(8);

    //for reach file to process)
    for (int i = 0; i < count; i++) {
        Runnable worker = new ProcessThreader(conf, i);
        executor.execute(worker);
    }

    executor.shutdown();
    JFrame PercentageFrame = new JFrame();
    PercentageFrame.setVisible(true);
    PercentageFrame.setSize(200, 200);
    PercentageFrame.repaint();

    while (!executor.isTerminated()) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            NarrowOptionPane.errorMessage("Interrupted: ", ex.getMessage());
        }
    }
    System.out.println("Complete");
}

运行按钮位于一个JPanel中,该JPanel位于一个JFrame中,Main Frame在main方法中实例化,并包装在invoke later方法中

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            JFrame frame = new MainFrame("PDF Producer");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
            frame.setSize(710, 530);
            frame.setResizable(false);
            frame.setLocationRelativeTo(null);
        }
    });
}

我对线程/执行器和 java swing 还很陌生,所以放轻松!谢谢

【问题讨论】:

  • 删除 while 循环它必须对您有所帮助,还可以从 ProcessThreader 更新您的 PercentageFrame。

标签: java swing executorservice


【解决方案1】:

从侦听器中执行的代码在事件调度线程上执行。因此 Thread.sleep() 导致 EDT 进入睡眠状态,这意味着 GUI 无法响应事件或重绘自身。

阅读 Concurrency In Swing 上的 Swing 教程部分了解更多信息。本教程中描述的一种解决方案是使用SwingWorker 来处理长时间运行的任务,并在结果可用时发布。

【讨论】:

    【解决方案2】:

    你的while循环块EDT,删除它,你的代码就可以工作了。

    请参阅下一个带有 ExecutorServiceJProgressBar 的示例:

    import java.awt.BorderLayout;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    import javax.swing.JFrame;
    import javax.swing.JProgressBar;
    
    public class Example extends JFrame {
    
        private static JProgressBar progress;
    
        public static void main(String[] args) {
            final JFrame f = new JFrame();
            progress = new JProgressBar();
            progress.setStringPainted(true);
            progress.setIndeterminate(true);
            ExecutorService newCachedThreadPool = Executors.newFixedThreadPool(1);
            for( int i =0; i<10;i++){
                final int j = i;
                Runnable r = new Runnable() {
    
                    @Override
                    public void run() {
                        progress.setString(j+"");
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                };
                newCachedThreadPool.submit(r);
            }
            f.getContentPane().add(progress,BorderLayout.CENTER);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.pack();
            f.setVisible(true);
        }
    
    }
    

    这里JFrame 显示在ExecutorService 中执行的Runnable 的编号。此外,如果您需要从 Runnables 中获取结果,请尝试使用 Callable 而不是 Runnable。这样,当您 submit Callable 时,您将获得 Future 实例,您可以从中获得结果。

    了解ExecutorsCallableFuture

    【讨论】:

    • 作为参考,SwingWorker 实现了 RunnableFuture&lt;T&gt;RunnableFuture&lt;T&gt;
    猜你喜欢
    • 1970-01-01
    • 2021-03-25
    • 1970-01-01
    • 2013-06-09
    • 2019-09-08
    • 2020-04-21
    • 1970-01-01
    • 1970-01-01
    • 2022-12-06
    相关资源
    最近更新 更多