Emil Kaminski
Emil Kaminski

Reputation: 1885

How to close a PrinterJob dialog in Java Swing?

I'm having the following issue:

Our Swing application has a timeout which returns the user back to the login frame.

If a user opens a print dialog and leaves it open, and then tries to hit the print button after the timeout, our applications fails and the user is presented with an error. (The application logic expects the user to make a print choice and then executes some logic afterwards).

Is it possible to somehow close the print dialog when the application times out, or add a custom timeout to the print dialog?

EDIT: What i have tried so far (MCVE):

public class JavaPrintTest implements Printable {
    public int print(Graphics g, PageFormat pf, int pageIndex) {
        if (pageIndex != 0)
            return NO_SUCH_PAGE;
        Graphics2D g2 = (Graphics2D) g;
        g2.setFont(new Font("Serif", Font.PLAIN, 36));
        g2.setPaint(Color.black);
        g2.drawString("Java Source and Support!", 144, 144);
        return PAGE_EXISTS;
    }

    public static void main(String[] args) {

        new java.util.Timer().schedule(
                new java.util.TimerTask() {
                    @Override
                    public void run() {
                        Window[] allWindows = Window.getWindows();
                        for (Window w:allWindows) {
                            w.setVisible(false);
                            w.dispose();
                        }
                        for (Frame frame : Frame.getFrames() ) {
                            frame.setVisible(false);
                            frame.dispose();
                        }
                    }
                },
                5000
        );

        PrinterJob pj = PrinterJob.getPrinterJob();
        pj.setPrintable(new JavaPrintTest());

        if (pj.printDialog()) {
            try {
                pj.print();
            } catch (PrinterException e) {
                System.out.println(e);
            }
        }
    }
}

I start a timer that after 5 seconds will try to close the print dialog where it tries to iterate over all windows and all frames, but the dialog dosn't close.

Upvotes: 0

Views: 548

Answers (1)

Leet-Falcon
Leet-Falcon

Reputation: 2147

You can find & close all active windows before returning to the log-in window:

private void logout() {
    Window[] allWindows = Window.getWindows();
    for (Window w:allWindows) {
        w.setVisible(false);
        w.dispose();
    }
    returnToLoginWindow();
}

EDIT: Print dialog is a native system dialog window which is not affected by dispose().
On Windows, for example, Java returns sun.awt.windows.WPrintDialog.
For such native dialogs, the only way I found is as a workaround:

for (Window w: allWindows) {
    //System.out.println(w.getClass().getSimpleName()+": "+w);
    try {
        Robot r = new Robot();
        r.keyPress(KeyEvent.VK_ESCAPE);
        r.keyRelease(KeyEvent.VK_ESCAPE);
    } catch (AWTException e) {
        e.printStackTrace();
    }
}

The following API does not affect the native dialog (at least on Windows):

WindowEvent windowClosing = new WindowEvent(w, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(windowClosing);
w.dispatchEvent(windowClosing);
w.setVisible(false);
w.dispose();

Upvotes: 2

Related Questions