davidahines
davidahines

Reputation: 4094

Trying to make a modal "Generating Report" dialog in Java

So, I have a reporting app that takes a while to generate a report and the users are complaining that there is no visual feedback that the report is running.

I have written a small class that is to be a modal dialog that will block the user from doing anything, show itself with the phrase,"Generating report...." until the report is actually done and then it will hide itself and regular use will return.

The issue that I'm having is that the dialog appears, the text appears, but the problem is that the runnable that is passed to it does not run.

This is the busy dialog:

package com.company.utilities.busydialog;

import java.awt.BorderLayout;
import java.awt.Cursor;
import javax.swing.JDialog;
import javax.swing.JLabel;

public class BusyDialog extends JDialog {

    private Runnable r;

    public BusyDialog (String Message, Runnable r) {
    super();
        this.r = r;
    this.setModal(true);

    this.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);

    this.setLayout(new BorderLayout());

    this.getContentPane().add(new JLabel(Message));

    this.pack();
    }

    public void show() {
    this.setVisible(true);
        this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        System.out.println("running report");
    r.run();
        this.setCursor(Cursor.getDefaultCursor());
    this.setVisible(false);
    }
} 

Here is the method that I call it:

private void dailyUsageSubmitButtonActionPerformed(java.awt.event.ActionEvent evt) {                                                       
    final Date date = this.dailyUsagePicker.getDate();
    final ReportController c = this.controller;
    final ProductionHRClientView view = this;
    BusyDialog dialog = new BusyDialog("Generating report...", new Runnable() {
        public void run() {
            c.generateDailyUsageReport(date, view);
        }
    });
    dialog.setResizable(false);
    dialog.setLocation(700,400);
    dialog.Show();
}    



EDIT: I tried this http://stackoverflow.com/questions/4542580/how-to-make-a-modal-jdialog-execute-code-immediately-upon-being-shown

and ended up with this class for BusyDialog:

package com.protocase.utilities.busydialog;

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JDialog;
import javax.swing.JLabel;

public class BusyDialog extends JDialog {

    public BusyDialog(String Message, final Runnable r) {
        super();
        this.setModal(true);
        this.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
        this.setLayout(new BorderLayout());
        this.getContentPane().add(new JLabel(Message));
        this.pack();
        this.addWindowListener(new WindowAdapter() {

            @Override
            public void windowOpened(WindowEvent e) {
                super.windowOpened(e);
                // do something
                doBusy(r);

            }
        });
    }

    private final void doBusy(Runnable r) {
        this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        r.run();
        this.setCursor(Cursor.getDefaultCursor());
        this.dispose();
    }


}

But this doesn't do the trick either.

Upvotes: 1

Views: 351

Answers (2)

vextorspace
vextorspace

Reputation: 934

Try this

package com.protocase.utils.dialogs;

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JDialog;
import javax.swing.JLabel;

public class BusyDlg extends JDialog {

    private Runnable r;

    public BusyDlg (String Message, Runnable r) {
    super();
        this.r = r;
    this.setModal(true);

        this.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);

        this.setLayout(new BorderLayout());

    this.getContentPane().add(new JLabel(Message));

        this.addWindowListener(new WindowAdapter() {

            @Override
            public void windowOpened(WindowEvent e) {
                super.windowOpened(e);
                // do something
                doBusy();
            }
        });




    this.pack();
    }

    public void Show() {
    this.setVisible(true);
    }

    public void doBusy() {
        this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        r.run();
        this.setCursor(Cursor.getDefaultCursor());
    this.setVisible(false);
        this.dispose();
    }
} 

Upvotes: 1

mKorbel
mKorbel

Reputation: 109823

all JComponents in Swing must be done on EDT, more in Concurency in Swing

then you have to:

1) this.setVisible(true); should be move to the last code line in the constructor

2) this.setVisible(true); would be wraped inside invokeLater()

3) is there long running task(s) then you have to look for invokeAndWait()

Upvotes: 2

Related Questions