4

(Java SE 6) I'm trying to create a pop-up dialog that displays a "please wait" message while my program does some time-intensive work. To do this, I've chosen to use a modeless JDialog, so that the program continues to run and does work while the JDialog is visible (if you use a modal one, the program will halt until the dialog is closed by the user).

The problem is that when you use a modeless dialog in this fashion the JDialog with a title appears, but the contents don't (I'm guessing they don't get painted for some reason). I've tried calling repaint etc but nothing seems to work.

Now, according to a bunch of people on the interwebs this is a genuine bug with Swing, and the only answers I've found are to not do things this way and find some other means of notifying the user to wait. I'm curious if anyone here has had this issue before and has figured out a work-around.

Thanks!

Riemannliness
  • 1,121
  • 1
  • 9
  • 9
  • 1
    A bug citation would be helpful. – trashgod Mar 19 '11 at 12:51
  • "I've chosen to use a modeless JDialog, so that the program continues to run and does work while the JDialog is visible". A modal dialog does *not* prevent any thread within the rest of the program from running, only the user's access to the controls of the parent. I have 2D animations that continue rendering while the user pops the configuration options in a JOptionPane. – Andrew Thompson Mar 19 '11 at 13:33
  • @Andrew Thompson is correct; here's a short [example](http://groups.google.com/group/comp.lang.java.programmer/msg/d95da1f8f9af2339). I'm still curious what "bug" you're trying avoid. – trashgod Mar 19 '11 at 17:25

4 Answers4

5

It´s not a bug, you have to run your heavy weight job and your light weight swing job in sepred thread´s next to the main thread. It´s necessary because of the logical inflictions between the Dialog GUI Thread and it´s ActionListenerEvents relation to the heavy weigth job in the backround. If you don´t seperate your Main thread will deterinate the Swing draw due to some notify Events. I had the same Problem, I tryed to monitor the progress of an FTP Upload Progress which I started out of a JFrame to show it in an JDialog.

First I tried:

//Activated by Upload Button
public void actionPerformed(ActionEvent e) {

    if("Upload".equals(e.getActionCommand())){

    // some Declarations

    new Thread(){

        public void run() {
            /*Run JDialog with the Upload - ProgressBar*/
            FileUploadProgressBar fileUploadProgressBar = new FileUploadProgressBar(localFile, remoteFile, ftpPersistence);
        }
    }.start();

/*Run the heavy weigth Job - the Upload*/
ftpPersistence.uploadFile(localFile, remoteFile);

// ...
    }

//...

}

But this way i gaint a JDialog FrameBorder ans a balck Content Pane but ...

Next try:

//Activated by Upload Button
public void actionPerformed(ActionEvent e) {

    if("Upload".equals(e.getActionCommand())){

    // some Declarations

    new Thread(){

        public void run() {
        /*Run JDialog with the Upload - ProgressBar*/
        FileUploadProgressBar fileUploadProgressBar = new FileUploadProgressBar(localFile, remoteFile, ftpPersistence);
    }
}.start();


new Thread(){

    public void run() 
            /*Run the heavy weigth Job - the Upload*/
            ftpPersistence.uploadFile(localFile, remoteFile);
        }
    }.start();
    // ... 
    }
//...
}

and finally it worked, hope it will help ;)

mornaner
  • 2,424
  • 2
  • 27
  • 39
elfu
  • 51
  • 1
  • 1
4

As an alternative, consider using SwingWorker and showing interim progress, as suggested in this example.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
2

I'm using this and it works - the original code (without the fix I found for repainting as it runs) is from here: http://inversionconsulting.blogspot.com/2008/03/java-jdialog-and-jprogressbar-example.html

but I consolidated it to (with slight changes):

JProgressBar pb = new JProgressBar(0,100);

pb.setPreferredSize(new Dimension(275,30));
pb.setString("Running");
pb.setStringPainted(true);
pb.setValue(0);

JLabel label = new JLabel("Progress: ");
JPanel center_panel = new JPanel();

center_panel.add(label);
center_panel.add(pb);

JDialog dialog = new JDialog((JFrame)null, "Working ...");

dialog.getContentPane().add(center_panel, BorderLayout.CENTER);
dialog.pack();
dialog.setVisible(true);
dialog.setLocationRelativeTo(null); // center on screen

In my code later on, when it is running through my loop (being 1 to 10 using the variable 'tot') I repaint the dialog, updating the progress bar as the program runs through the loop, thusly (this is not given on the above page link) (I am not using multiple threads, all of this is in the main thread):

//set progress bar
pb.setValue(tot*10);
//repaint it
dialog.getContentPane().paintAll(pb.getGraphics());

It took a lot of time and trial and error to find this solution. Hope it works for you as it does for me.

Mat
  • 202,337
  • 40
  • 393
  • 406
davejr
  • 21
  • 1
  • Oh yes, using the latest java, the dialog's initialization and being set visible happens right at the start of processing my loop (before going in), and at the end of my loop, right outside it, I dialog.dispose(). – davejr May 28 '11 at 23:30
0

Have You tried validate() (it is needed after adding components to a container) ? Also consider posting source code, so that we may check it. Good luck.

KarolDepka
  • 8,318
  • 10
  • 45
  • 58
  • Yea, I've tried every form of invoking the components to paint. The reason I've not added source code is because I know this is a bug with Swing, and I'm looking for either alternative implementations (like using SwingWorker as has been suggested), or someone who has found a work-around for it that is OS-independent - this problem does not occur on a Windows machine. – Riemannliness Mar 19 '11 at 13:08
  • I sense, that there must be a workaround to this, while still using JDialog. – KarolDepka Mar 19 '11 at 13:43