【问题标题】:SwingWorker in Java [closed]Java中的SwingWorker [关闭]
【发布时间】:2012-09-20 10:47:12
【问题描述】:

我有问题。

我有一个JFrame。它将创建一个JDialog

JDialog 上的按钮被按下时,它应该被释放并且应该发送一封电子邮件。 同时,我需要另一个JDialog 以不确定的JProgressBar 出现。发送电子邮件时,JDialog 应该被丢弃(并创建一个新的)或者它的内容应该改变。

我已经失败了几个小时,所以我问任何人他(或她)是否愿意给我写一个伪代码来做我想做的事。

只是看看应该在SwingWorker 类中包含什么(或者如果您认为它更好,则使用多线程),何时应该创建/处置JDialog(s),以及在哪里粘贴电子邮件发送...

我知道我在这里要求一个完整的解决方案,但我已经陷入困境并且已经失败了很多次......这是我最后的手段......

【问题讨论】:

  • 查看this answer 以了解您需要调整doInBackGround 以发送电子邮件的示例
  • 你最后的手段永远不应该是要求 StackOverflow 读者为你编写代码。发布可以以正确问答格式回答的具体问题。或聘请合同程序员。
  • -1 并投票以离题结束(这不是问题,而是其他人已经指出的工作请求)
  • 您应该花时间阅读Concurrency in Swing 课程,这样可以减轻您的压力

标签: java multithreading swing swingworker


【解决方案1】:

我为您做了一个简短的示例,希望对您有所帮助。基本上显示了一个带有按钮的JFrame

当点击框架上的JButton 时,将出现一个JDialog 和另一个JButton发送电子邮件) - 这将代表电子邮件对话框

当按下emailDialog 上的JButton 时,它会处理emailDialog 并创建一个新的JDialog 来保存进度条(或者在这种情况下是一个简单的@987654333 @):

然后它创建并执行SwingWorker 以发送电子邮件,并在完成后显示JDialogdispose() 并显示发送成功的JOptionPane 消息:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class Test {

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

            @Override
            public void run() {
                new Test().createAndShowUI();
            }
        });
    }

    private void createAndShowUI() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        initComponents(frame);
        frame.setPreferredSize(new Dimension(300, 300));//testing purposes
        frame.pack();
        frame.setVisible(true);
    }

    private void initComponents(final JFrame frame) {

        final JDialog emailDialog = new JDialog(frame);
        emailDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        emailDialog.setLayout(new BorderLayout());

        JButton sendMailBtn = new JButton("Send Email");
        sendMailBtn.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                //get content needed for email from old dialog

                //get rid of old dialog
                emailDialog.dispose();

                //create new dialog
                final JDialog emailProgressDialog = new JDialog(frame);
                emailProgressDialog.add(new JLabel("Mail in progress"));
                emailProgressDialog.pack();
                emailProgressDialog.setVisible(true);

                new Worker(emailProgressDialog).execute();

            }
        });

        emailDialog.add(sendMailBtn, BorderLayout.SOUTH);
        emailDialog.pack();

        JButton openDialog = new JButton("Open emailDialog");
        openDialog.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                emailDialog.setVisible(true);
            }
        });

        frame.getContentPane().add(openDialog);

    }
}

class Worker extends SwingWorker<String, Object> {

    private final JDialog dialog;

    Worker(JDialog dialog) {
        this.dialog = dialog;
    }

    @Override
    protected String doInBackground() throws Exception {

        Thread.sleep(2000);//simulate email sending

        return "DONE";
    }

    @Override
    protected void done() {
        super.done();
        dialog.dispose();
        JOptionPane.showMessageDialog(dialog.getOwner(), "Message sent", "Success", JOptionPane.INFORMATION_MESSAGE);

    }
}

【讨论】:

  • 你应该为我的公司工作,你看起来很便宜! ;-)
  • 可能很便宜,但代码不正确。 doInBackground 不会在 EDT 上调用,因此它不应调用 JOptionPane.showMessageDialogdialog.dispose
  • 如果 doInBackground 会在 EDT 上运行,为什么还要费心创建一个 SwingWorker ... doInBackground 在工作线程上运行,无论你在哪里构造或执行SwingWorker(这是一件好事)。看看execute方法的源码就知道了
  • 我从不建议不要使用SwingWorker。您使用SwingWorker,但在doInBackground 方法中根本不执行任何与Swing 相关的操作。我在问题下的第一条评论中链接到一个示例
  • @DavidKroukamp 只需覆盖 SwingWorker 中的方法 done() 并将调用移至该方法中的 JOptionPane.showMessageDialog(frame, "Message sent", "Success", JOptionPane.INFORMATION_MESSAGE);。一旦 doInBackground() 完成并在 EDT 上运行,就会调用方法 done()
【解决方案2】:

@大卫·克鲁坎普

来自 Substance L&F 的输出(您对用于测试目的的 EDT 有任何不确定性)

run:
JButton openDialog >>> Is there EDT ??? == true
Worker started >>> Is there EDT ??? == false
waiting 30seconds 
Worker endeded >>> Is there EDT ??? == false
before JOptionPane >>> Is there EDT ??? == false
org.pushingpixels.substance.api.UiThreadingViolationException: 
     Component creation must be done on Event Dispatch Thread

还有另外 200 行关于细节的内容

输出是"correct container created out of EDT"

我将在另一个 L&F 上进行测试,Nimbus 可能存在问题,SystemLokkAndFeel 在大多数情况下并不关心 EDT 上的大错误(对 EDT 的敏感性非常不同),Metal 默认情况下没有任何问题Windows 平台和 Java6,那么您的示例也适用于第二个基础

编辑

Nimbus 也不在乎

来自代码

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.plaf.FontUIResource;

public class Test {

    public static void main(String[] args) throws Exception {
        try {
            for (UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    UIManager.getLookAndFeelDefaults().put("nimbusOrange", (new Color(127, 255, 191)));

                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
        } catch (InstantiationException ex) {
        } catch (IllegalAccessException ex) {
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
        }
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                /*try {
                    UIManager.setLookAndFeel(
                            "org.pushingpixels.substance.api.skin.SubstanceOfficeBlue2007LookAndFeel");
                    UIManager.getDefaults().put("Button.font", new FontUIResource(new Font("SansSerif", Font.BOLD, 24)));
                    UIManager.put("ComboBox.foreground", Color.green);
                } catch (Exception e) {
                }*/
                new Test().createAndShowUI();
            }
        });
    }

    private void createAndShowUI() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        initComponents(frame);
        frame.setPreferredSize(new Dimension(300, 300));//testing purposes
        frame.pack();
        frame.setVisible(true);
    }

    private void initComponents(final JFrame frame) {

        final JDialog emailDialog = new JDialog(frame);
        emailDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        emailDialog.setLayout(new BorderLayout());
        JButton sendMailBtn = new JButton("Send Email");
        sendMailBtn.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                //get content needed for email from old dialog
                //get rid of old dialog
                emailDialog.dispose();
                //create new dialog
                final JDialog emailProgressDialog = new JDialog(frame);
                emailProgressDialog.add(new JLabel("Mail in progress"));
                emailProgressDialog.pack();
                emailProgressDialog.setVisible(true);
                new Worker(emailProgressDialog, frame).execute();

            }
        });
        emailDialog.add(sendMailBtn, BorderLayout.SOUTH);
        emailDialog.pack();
        JButton openDialog = new JButton("Open emailDialog");
        openDialog.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("JButton openDialog >>> Is there EDT ??? == " + SwingUtilities.isEventDispatchThread());
                emailDialog.setVisible(true);
            }
        });
        frame.getContentPane().add(openDialog);
    }
}

class Worker extends SwingWorker<String, Object> {

    private final JDialog dialog;
    private final JFrame frame;

    Worker(JDialog dialog, JFrame frame) {
        this.dialog = dialog;
        this.frame = frame;
    }

    @Override
    protected String doInBackground() throws Exception {
        System.out.println("Worker started >>> Is there EDT ??? == " + SwingUtilities.isEventDispatchThread());
        System.out.println("waiting 30seconds ");
        Thread.sleep(30000);//simulate email sending
        System.out.println("Worker endeded >>> Is there EDT ??? == " + SwingUtilities.isEventDispatchThread());
        dialog.dispose();
        System.out.println("before JOptionPane >>> Is there EDT ??? == " + SwingUtilities.isEventDispatchThread());
        JOptionPane.showMessageDialog(frame, "Message sent", "Success", JOptionPane.INFORMATION_MESSAGE);
        System.out.println("before JOptionPane >>> Is there EDT ??? == " + SwingUtilities.isEventDispatchThread());
        return null;
    }
}

【讨论】:

  • +1 谢谢我知道我哪里出错了。根据@GuillaumePolet 答案更新代码
猜你喜欢
  • 2020-12-16
  • 1970-01-01
  • 1970-01-01
  • 2011-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-10
相关资源
最近更新 更多