-4

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...

JavaTechnical
  • 8,846
  • 8
  • 61
  • 97
Karlovsky120
  • 6,212
  • 8
  • 41
  • 94
  • 1
    See [this answer](http://stackoverflow.com/a/8917565/1076463) for an example where you need to adjust the `doInBackGround` to send the email – Robin Sep 28 '12 at 14:28
  • 3
    Your last resort should never be to ask StackOverflow readers to write your code for you. Post specific questions that can be answered in the correct Q&A format. Or hire a contract programmer. – Duncan Jones Sep 28 '12 at 14:33
  • 3
    -1 and voted to close as off-topic (it's not a question but a work request as others already noted) – kleopatra Sep 28 '12 at 14:48
  • You should take the time to read through the [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html) lesson, would have saved you the stress – MadProgrammer Sep 28 '12 at 21:30

2 Answers2

12

I did a short example for you hope it helps. Basically a JFrame witha button is shown:

enter image description here

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

enter image description here

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):

enter image description here

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:

enter image description here

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);

    }
}
David Kroukamp
  • 36,155
  • 13
  • 81
  • 138
  • 2
    You should work for my company, you seem cheap! ;-) – Duncan Jones Sep 28 '12 at 14:49
  • +1 LMAO I just enjoy coding :) – David Kroukamp Sep 28 '12 at 14:50
  • 2
    Might be cheap, but the code is incorrect. The `doInBackground` is not invoked on the EDT, so it should not call `JOptionPane.showMessageDialog` nor `dialog.dispose` – Robin Sep 28 '12 at 15:18
  • @Robin but the `JButton` whos `actionPerformed()` method calls the `SwingWorker` and disposes of the `JDialog` is created on the EDT thus the `SwingWorker` is invoked on the EDT? – David Kroukamp Sep 28 '12 at 15:25
  • 2
    If the `doInBackground` would run on the EDT, why bother with creating a `SwingWorker` at all ... the `doInBackground` runs on a worker thread, no matter where you construct or execute the `SwingWorker` (which is a good thing). Just look at the source code of the `execute` method – Robin Sep 28 '12 at 15:26
  • 3
    I never suggested to not use a `SwingWorker`. You use a `SwingWorker` but simply do not perform any Swing related operations in the `doInBackground` method. I linked to an example in my first comment under the question – Robin Sep 28 '12 at 15:30
  • 1
    @David Kroukamp please see my post here, (@Robin +++) – mKorbel Sep 28 '12 at 16:14
  • 5
    @DavidKroukamp simply override the method `done()` in your SwingWorker and move the call to `JOptionPane.showMessageDialog(frame, "Message sent", "Success", JOptionPane.INFORMATION_MESSAGE);` in that method. The method `done()` is invoked once `doInBackground()` has finished and it runs on the EDT. – Guillaume Polet Sep 28 '12 at 16:26
  • 2
    @DavidKroukamp: Guillaume is right; you can also listen for `SwingWorker.StateValue.DONE` in a `PropertyChangeListener`, for [example](http://stackoverflow.com/a/7054627/230513). – trashgod Sep 28 '12 at 16:50
  • @Robin thank you for the advice I welcome criticism, I must ask though to help me understand, you used a `static` `JProgressBar` so is that what I must use a `static` `JDialog`? From others answers I gather I should call `dispose()` and the `JOptionPane` in an *overridden* method of `done()` is this correct? I apologize for making a mistake and confusing the OP more. – David Kroukamp Sep 28 '12 at 19:14
  • 1
    @Karlovsky120 please see my upadted post my code had a fatal flaw which was fixed by overriding `done()` and calling the joptionpane and dispose from within there (on the EDT thread) – David Kroukamp Sep 28 '12 at 19:24
  • 2
    @DavidKroukamp No, no need for it to be static. That was more laziness on my part for that code snippet. You should indeed place the EDT-involving calls either in the `process` method, in the `done` method or by attaching a listener which is also invoked on the EDT. The `SwingWorker` class javadoc contains some sample code as well – Robin Sep 28 '12 at 20:47
  • 1
    +1 for happy ending :-) Nitpicking: no need to keep a reference (in the worker) to the frame, the dialog already has it - getOwner is what you want to use – kleopatra Sep 29 '12 at 08:29
  • @Kleopatra :) +1 thank you for the advice will update code soon – David Kroukamp Sep 29 '12 at 08:56
4

@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"

enter image description here

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

enter image description here

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;
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319