SwingWorker,未调用done()方法

时间:2014-04-21 09:59:25

标签: java multithreading swing swingworker

这只是SwingWorker的一个实现:

class GuiWorker extends SwingWorker<Integer, Integer> {
    private JFrame frame = new JFrame();
    private JDialog dialog = new JDialog(frame, "Loadin data", true);
    private JProgressBar progressBar = new JProgressBar();

    private Statistics st = new Statistics();

    public GuiWorker(GraphEditor editor, Statistics st) {
        this.st = st;

        Window mainWindow = SwingUtilities.windowForComponent(editor
                .getGraphComponent().getParent());
        dialog.setSize(400, 200);

        int x = mainWindow.getX() + (mainWindow.getWidth() - dialog.getWidth())
                / 2;
        int y = mainWindow.getY()
                + (mainWindow.getHeight() - dialog.getHeight()) / 2;
        progressBar.setString("Have fun to wait some time...");
        progressBar.setStringPainted(true);
        progressBar.setIndeterminate(true);
        dialog.add(progressBar);
        dialog.setModal(true);
        dialog.setLocation(x, y);
        dialog.setVisible(true);
    }

    @Override
    protected Integer doInBackground() throws Exception {
        st.loadInitialData();
        return 0;
    }

    @Override
    protected void done() {
        dialog.setVisible(false);
        JLabel label = new JLabel("Task Complete");
        dialog.getContentPane().remove(progressBar);
        dialog.getContentPane().add(label);
        dialog.getContentPane().validate();
        dialog.setVisible(false);
    }
}

diaglog永远不会隐藏的问题,直到我强行关闭它(当任务完成时必须隐藏它)。 我注意到loadInitialData()方法是一种从我的DB收集一些统计信息的方法,需要几秒钟。

更新:我确信在关闭done()时会调用dialog方法。

更新: 我在哪里使用GuiWorker在这里:

mainTabs.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    switch (mainTabs.getSelectedIndex()) {
                    case 0:
                    case 1:
                    case 2: // stats tab
                        GuiWorker gw = new GuiWorker(editor,st);
                        gw.execute();
                        break;
                    default:
                        break;
                    }
                }
            });

1 个答案:

答案 0 :(得分:4)

所有挥杆事件都在Event Dispatch Thread内进行。因此,您添加到ChangeListener的{​​{1}}在事件调度线程中运行。

在事件监听器中,您实例化mainTabs并在该构造函数中通过调用GuiWorker打开对话框。

你的JDialog实例是dialog.setVisible(true);,在模态对话框上调用modal将阻塞调用线程,在你的情况下是事件调度线程。因此,在对话框关闭之前,不会调用setVislbe(true)。这就是为什么在关闭对话框之前不会调用gw.execute();方法的原因。

要让您的代码正常工作,您可以尝试不在构造函数中调用done,而是从setVisible(true)提供一个方法来设置对话框的可见性。然后在致电GuiWorker后致电gw.execute();

澄清一下,试试

gw.setVisible(true)

class GuiWorker extends SwingWorker<Integer, Integer> {
    private JFrame frame = new JFrame();
    private JDialog dialog = new JDialog(frame, "Loadin data", true);
    private JProgressBar progressBar = new JProgressBar();

    private Statistics st = new Statistics();

    public GuiWorker(GraphEditor editor, Statistics st) {
        this.st = st;

        Window mainWindow = SwingUtilities.windowForComponent(editor
                .getGraphComponent().getParent());
        dialog.setSize(400, 200);

        int x = mainWindow.getX() + (mainWindow.getWidth() - dialog.getWidth())
                / 2;
        int y = mainWindow.getY()
                + (mainWindow.getHeight() - dialog.getHeight()) / 2;
        progressBar.setString("Have fun to wait some time...");
        progressBar.setStringPainted(true);
        progressBar.setIndeterminate(true);
        dialog.add(progressBar);
        dialog.setModal(true);
        dialog.setLocation(x, y);
    }

    @Override
    protected Integer doInBackground() throws Exception {
        st.loadInitialData();
        return 0;
    }

    @Override
    protected void done() {
        dialog.setVisible(false);
        JLabel label = new JLabel("Task Complete");
        dialog.getContentPane().remove(progressBar);
        dialog.getContentPane().add(label);
        dialog.getContentPane().validate();
        dialog.setVisible(false);
    }

   public void setVisible(boolean visible) {
        dialog.setVisible(visible);
   }
}