【问题标题】:SwingWorker setting a flag after finishing its workSwingWorker 完成工作后设置标志
【发布时间】:2013-06-07 11:41:26
【问题描述】:

我已经组装了一个可以打开文本文件并允许用户编辑它们的应用程序(例如:文本编辑器)

有些文本文件可以任意大,因此打开它们需要一些时间。我添加了一个进度条来通知用户实际发生的事情,并且正在使用一个 swing worker 来执行实际的文件加载,给它一个文本区域的引用来转储所有的文本。

我在主应用程序中还有一个名为isFileLoaded 的标志,如果有文件打开则为真,否则为假。理想情况下,swing worker 应该在完成加载文件并完成它需要做的任何处理后设置该值。

我将 swing worker 编写为一个单独的类,因此它没有嵌套在包含所有 GUI 逻辑的主 Frame 类中,主要是因为我不喜欢纯粹出于审美原因在类中定义类。因此,我目前正在将整个 Frame 的引用传递给 swing worker 并让它设置标志的值。

这是做事的好方法吗?有更好的方法吗?

【问题讨论】:

    标签: java swing swingworker


    【解决方案1】:

    考虑添加一个PropertyChangeListener,它包含对您的Frame 的引用(一个匿名内部类就可以了)并监听"state" 属性。当SwingWorker 完成时,事件的值将等于StateValue.DONE

    这是一个完整的示例:

    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.beans.PropertyChangeEvent;
    import java.beans.PropertyChangeListener;
    import java.util.List;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JProgressBar;
    import javax.swing.SwingUtilities;
    import javax.swing.SwingWorker;
    import javax.swing.SwingWorker.StateValue;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class TestSwingWorker {
    
        private JProgressBar progressBar;
    
        protected void initUI() {
            final JFrame frame = new JFrame();
            frame.setTitle(TestSwingWorker.class.getSimpleName());
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JButton button = new JButton("Clik me to start work");
            button.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    doWork();
                }
            });
            progressBar = new JProgressBar(0, 100);
            frame.add(progressBar, BorderLayout.NORTH);
            frame.add(button, BorderLayout.SOUTH);
            frame.pack();
            frame.setVisible(true);
        }
    
        private boolean someFlag;
    
        protected void doWork() {
            SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {
                @Override
                protected Void doInBackground() throws Exception {
                    for (int i = 0; i < 100; i++) {
                        // Simulates work
                        Thread.sleep(10);
                        publish(i);
                    }
                    return null;
                }
    
                @Override
                protected void process(List<Integer> chunks) {
                    progressBar.setValue(chunks.get(chunks.size() - 1));
                }
    
                @Override
                protected void done() {
                    progressBar.setValue(100);
                    progressBar.setStringPainted(true);
                    progressBar.setString("Done");
                }
            };
            worker.getPropertyChangeSupport().addPropertyChangeListener("state", new PropertyChangeListener() {
    
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    if (StateValue.DONE.equals(evt.getNewValue())) {
                        someFlag = true;
                    }
                }
            });
            worker.execute();
        }
    
        public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
                UnsupportedLookAndFeelException {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new TestSwingWorker().initUI();
                }
            });
        }
    }
    

    【讨论】:

    • 我对听众不熟悉,但在阅读了一些摇摆教程之后,看起来如果我真的想获得一些响应式应用程序,我需要开始使用它们。您能否提供一些 sn-ps 显示我将在何处添加侦听器以及摇摆工作人员将如何使用它?
    【解决方案2】:

    你应该稍微重构你的代码以避免使用整个框架,这确实不是很干净(但如果它有效,谁在乎)。

    如果你想从设计的角度更酷,你应该使用模型:

    class FileModel
    {
        boolean isLoading;
        // getter and setter that notifies
    }
    

    只将此模型传递给您的工作人员,完成后设置标志。

    【讨论】:

    • 在多个组件之间共享一个对象听起来是个好主意,因为我可以统一访问来自各种对象的数据并提供额外的抽象层。
    • 这是 MVC 模式及其所有衍生模式的本质:分离关注点:一方面是视图,另一方面是逻辑和数据。 :)
    猜你喜欢
    • 2021-06-19
    • 2020-08-29
    • 1970-01-01
    • 2013-04-17
    • 2018-12-13
    • 2011-12-28
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    相关资源
    最近更新 更多