当前位置: 首页 > 面试题库 >

与swingworker的对话是一只鸡/蛋

勾安翔
2023-03-14
问题内容

我试图通过不在主线程(EDT)上执行长任务来遵循Java最佳实践。因此,我计划将“
swingWorker”与“模态对话框”一起使用。这样,模式对话框会阻止用户执行任何操作,直到该任务完成为止,并且我可以在过程进行时更新对话框上的状态。

现在的问题是,使用模式对话框,它不仅会阻止用户,而且在调用setVisible之后也不会阻止用户

所以如果我这样做

dialog.setVisible(true);
new SwingWorkerTask().execute(); //This does not get called

如果我愿意

new SwingWorkerTask().execute();
dialog.setVisible(true); // Well what the point of setting visible after the fact.

那么,如何在执行任务时阻止用户操作并显示对话框?

谢谢


问题答案:

如果您这样做的话,那只是鸡/蛋。您可以在EDT上构造所有Swing对象,然后SwingWorker通过指示EDT通过执行它们来让您(或任何其他线程)管理所有更新SwingUtilities.invokeLater(Runnable)

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class RudeProgressBar extends JFrame {

    private JButton button;

    public RudeProgressBar() {
        setTitle("Rude Progress Bar");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        button = new JButton("Do teh work");
        add(button, BorderLayout.SOUTH);

        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JDialog dialog = new JDialog(RudeProgressBar.this, true);
                dialog.setTitle("Doing teh work");
                dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
                final JProgressBar progressBar = new JProgressBar(0, 100);
                dialog.setLayout(new BorderLayout());
                dialog.add(progressBar);
                dialog.setSize(100, 100);
                dialog.setLocationRelativeTo(RudeProgressBar.this);
                MyTask task = new MyTask(dialog);
                task.addPropertyChangeListener(new PropertyChangeListener() {
                    @Override
                    public void propertyChange(PropertyChangeEvent evt) {
                        if ("progress".equals(evt.getPropertyName())) {
                            progressBar.setValue((Integer)evt.getNewValue());
                        }
                    }
                });
                task.execute();
            }
        });

        setSize(200, 200);
        setLocationRelativeTo(null);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new RudeProgressBar().setVisible(true);
            }
        });
    }

    private class MyTask extends SwingWorker<Void, Void> {

        private final JDialog dialog;

        public MyTask(JDialog dialog) {
            this.dialog = dialog;
        }

        @Override
        protected Void doInBackground() throws Exception {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    dialog.setVisible(true);
                }
            });

            int progress = 0;
            for (int i = 0; i < 5; i++) {
                Thread.sleep(1000);
                setProgress(progress += 20);
            }

            return null;
        }

        @Override
        protected void done() {
            dialog.setVisible(false);
            dialog.dispose();
        }
    }
}

如果您担心invokeLater实现(内部SwingWorker.doInBackground)在执行之后会被执行SwingWorker.done,只需将代码done放入另一个invokeLater。通过这样做,您可以将Runnable实现排入队列以让EDT以特定顺序执行它们。即使从EDT本身调用此方法,也会发生排队。

请注意,如果您看一下SwingWorker实现,您会看到它依赖于javax.swing.Timer执行done()Timer本身调用invokeLater,因此done再次在内部调用它无济于事。但是,如果这样做,不会有任何问题。



 类似资料:
  • 在Netbeans中,我创建了一个GUI项目,该项目使用框架前端,我可以添加组件并双击以编辑其事件。我指的是有“源”、“设计”和“历史”选项卡的窗口。 以下是组件和关系: 1-打开文件选择器的按钮。 2-显示文件选择器结果的文本区域。如果用户选择一个文件,它将在文本区域显示文件名;否则它会写“被用户取消”。 3-同时,如果用户选择了一个文件,我想打开一个“please wait”(请等待)对话框,

  • 对话画面 在上一教程里已经讲到了如何设定图片和调整坐标。 这些操作对于标题画面的按钮和对话框上的按钮都是一样的。 因此这篇将主要说一下不同的部分。 进入游戏之后,通常就进入到了对话画面。 一个普通的AVG游戏通常会有一个对话框,用来显示人物的交谈,上面则有一些可以操作的按钮,例如保存、读取、快进、查看对话记录等等。 有一些游戏会有主角或其他人的表情图像,也有些游戏则会有对话专用和叙述专用的对话框。

  • 问题内容: 使用代替或的优点是什么? 问题答案: Thread和Runnable是Java 1.0的一部分;他们和当时一样出色。 从那时起,新的并发类将提炼出关于多线程的所有知识(感谢您,Doug Lea和其他人)。编写多线程代码非常困难。包括SwingWorker在内的新的并发类都试图使其变得更容易。 首先请注意用于强类型键入的泛型。有内置的机制可以发布和处理最终结果和中间结果。 可以使用Thr

  • 问题内容: 是否有与Java SwingWorker类等效的JavaFX? 我知道JavaFX Task,但是有了它,您只能发布String消息或进度。我只想在GUI线程中调用方法,就像使用SwingWorker一样(通过发布任意类型的消息)。 这是我的意思的一个例子: 解 非常感谢您的回答。我正在寻找的解决方案是使用Platform.runLater(Runnable guiUpdater) 。

  • 我想创建一个底部工作表对话框。看起来像下面的图像在这里输入图像描述 我尝试过许多方法,如SharedPreferences。但它不起作用

  • 问题内容: 我想使我的网站一次只允许一个会话。例如,假设用户已经登录到我在firefox上的网站,如果该用户再次登录到另一台浏览器(例如同一台计算机或另一台计算机上的Opera),则Firefox上的会话将被破坏。但是,如果仍为一届会议,则有关Firefox的会议仍将保留。我可以知道该怎么做吗?我正在使用php和apache。谢谢。 问候。本杰明 问题答案: 我建议您做这样的事情: 假设用户“ A