Search code examples
javaconcurrencyjoptionpaneswingworker

SwingWorker doInBackground() doesn't work


I am trying to show a progress bar while I do some tasks on a database. The Progress bar, however, freezes and the Things I want to do on the database aren't executed. I understand that, in order to guarantee proper concurrency in Swing I need to do the database tasks on a secondary thread. I also understand that somehow my bug has to do with JOptionPane. But I can't come up with a solution to fix it. Here is the Code for my Progress Dialog:

public class ProgressDialog extends JDialog {
/**
 * 
 */
    private static final long serialVersionUID = 1L;

    public ProgressDialog() {

        setModal(true);
        setTitle("Fortschritt");
        setSize(200, 100);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);

        JProgressBar pb = new JProgressBar();
        pb.setIndeterminate(true);
        pb.setValue(0);
        add(pb);

        setVisible(true);
   }
}

And here is the Code where I call this constructor:

int result = JOptionPane.showConfirmDialog(GUIAutoTest.jtable,
    "Schaden mit Testkonfig = " + index + " anlegen ?", "Bestätigen",
    JOptionPane.YES_NO_OPTION);

if (result == JOptionPane.YES_OPTION) {
new SwingWorker<Void, Void>() {
    final  ProgressDialog pd = new ProgressDialog();
    @Override
    protected Void doInBackground() throws Exception {
        InitTestLauf itl;
        try {
            itl = new InitTestLauf(index);
            StartTestLauf stl = new StartTestLauf(itl.getIdTstLauf());
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void done() {
        System.out.println("done");
        pd.setVisible(false);
    }
}.execute();

JOptionPane.showMessageDialog(GUIAutoTest.jtable,
        "Schaden angelegt. " + "Schadennummer: " + StartTestLauf.getSchadenNr(),
        "Schaden angelegt", JOptionPane.PLAIN_MESSAGE);

It doesn't matter, what happens inside the doInBackground()-block , not even System.out.println("print something") does work. Where is my mistake ?

Thanks in advance!


Solution

  • I made an example that uses a progress bar with a dialog and a swingworker.

    import javax.swing.JProgressBar;
    import javax.swing.SwingWorker;
    import java.util.List;
    
    /**
     * Created on 13.06.17.
     */
    public class DialogJunker {
        static class ProgressDialog extends JDialog {
            JProgressBar bar;
            ProgressDialog(){
                setModal(true);
                bar = new JProgressBar();
                add(bar);
                pack();
            }
            void setProgress(int i){
                bar.setValue(i);
            }
        }
        public static void main(String[] args){
    
            JFrame frame = new JFrame("diddly dialog");
            JButton button = new JButton("start");
            button.addActionListener(evt->{
                ProgressDialog log = new ProgressDialog();
    
                new SwingWorker<Void, Integer>(){
                    @Override
                    public Void doInBackground(){
                        for(int i = 0; i<100; i++){
                            try{
                                Thread.sleep(10);
                                publish(i);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        return null;
                    }
                    @Override
                    public void done(){
                        log.setVisible(false);
                        log.dispose();
                    }
                    @Override
                    protected void process(List<Integer> ints){
                        log.setProgress(ints.get(0));
                    }
    
    
                }.execute();
    
                log.setVisible(true);
    
            });
            frame.add(button);
            frame.pack();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
    
        }
    }
    

    This example will show a dialog with a progress bar that gets updated, then close the dialog when finished.

    After reviewing you code a little more, I do see the problem. You are constructing the ProgressDialog in the SwingWorker class, but you set your progress dialog to visible, which blocks. Take note that I have solved quite a few issues.

    • I call set visible after starting the swing worker.
    • I publish the results so that the dialog actually gets updated.
    • I keep a reference to the progress bar, so it actually can be updated.