Java中的SwingWorker [关闭]
Posted
技术标签:
【中文标题】Java中的SwingWorker [关闭]【英文标题】:SwingWorker in Java [closed] 【发布时间】:2012-09-20 10:47:12 【问题描述】:我有问题。
我有一个JFrame
。它将创建一个JDialog
。
当JDialog
上的按钮被按下时,它应该被释放并且应该发送一封电子邮件。
同时,我需要另一个JDialog
以不确定的JProgressBar
出现。发送电子邮件时,JDialog
应该被丢弃(并创建一个新的)或者它的内容应该改变。
我已经失败了几个小时,所以我问任何人他(或她)是否愿意给我写一个伪代码来做我想做的事。
只是看看应该在SwingWorker
类中包含什么(或者如果您认为它更好,则使用多线程),何时应该创建/处置JDialog
(s),以及在哪里粘贴电子邮件发送...
我知道我在这里要求一个完整的解决方案,但我已经陷入困境并且已经失败了很多次......这是我最后的手段......
【问题讨论】:
查看this answer 以了解您需要调整doInBackGround
以发送电子邮件的示例
你最后的手段永远不应该是要求 *** 读者为你编写代码。发布可以以正确问答格式回答的具体问题。或聘请合同程序员。
-1 并投票以离题结束(这不是问题,而是其他人已经指出的工作请求)
您应该花时间阅读Concurrency in Swing 课程,这样可以减轻您的压力
【参考方案1】:
我为您做了一个简短的示例,希望对您有所帮助。基本上显示了一个带有按钮的JFrame
:
当点击框架上的JButton
时,将出现一个JDialog
和另一个JButton
(发送电子邮件) - 这将代表电子邮件对话框:
当按下emailDialog
上的JButton
时,它会处理emailDialog
并创建一个新的JDialog
来保存进度条(或者在这种情况下是一个简单的@987654333 @):
然后它创建并执行SwingWorker
以发送电子邮件,并在完成后显示JDialog
的dispose()
并显示发送成功的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.showMessageDialog
或 dialog.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 答案更新代码以上是关于Java中的SwingWorker [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
java - JLabel setForeground 在 SwingWorker 中不起作用
Java - 如何将 JProgressBar 与 SwingWorker 一起使用