问题
I have a problem.
I have a JFrame
. It will create a JDialog
.
When button on JDialog
is pressed it should be disposed and an email should be sent.
At the same time, I need another JDialog
to appear with indetermined JProgressBar
. When email is sent, JDialog
should either be disposed (and new one creted) or it's contents should change.
I have been failing with this for several hours now, so I'm asking enyone if he (or she) would be kind enough to write me a pseudo-code that will do what I want.
Just to see what should be included in SwingWorker
class (or use multithreading if you think it's better), when JDialog
(s) should be created/disposed, and where to stick in the email sending...
I know I'm asking for a finished solution here, but I'm on a dedline and have failed so many times already... This was my last resort...
回答1:
I did a short example for you hope it helps. Basically a JFrame
witha button is shown:

when the JButton
on the frame is clicked a JDialog
will appear with another JButton
(Send Email) - this would represent the email dialog:

When the JButton
on the emailDialog
is pressed it disposes of the emailDialog
and creates a new JDialog
which will hold the progressbar (or in this case a simple JLabel
):

and then it creates and executes the SwingWorker
to send the email and dispose()
of the JDialog
when its done and show a JOptionPane
message showing success of the sending:

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);
}
}
回答2:
@David Kroukamp
output from Substance L&F (in you have got any uncertainties about EDT ust that for testing purposes)
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
and another 200lines about details
output is "correct container created out of EDT"

I'll test that on another L&F, there couls be issue with Nimbus, SystemLokkAndFeel in most cases doesn't care about big mistakes on EDT (very different sensitivity to the EDT), Metal by default haven't any issue on Windows platform and for Java6, then your example works on second bases too
EDIT
Nimbus doeasn't care too

from code
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;
}
}
来源:https://stackoverflow.com/questions/12641887/swingworker-in-java