Innerhalb des EDT auf einen anderen Thread warten, ohne dass GUI einfriert?

DarthShader

Erfahrenes Mitglied
Hallo,

ich habe ein kleines "Problem" bezüglich der GUI Programmierung in Swing sowie einem nebenläufigen Thread.

Das Szenario (hier etwas konstruiert) ist relativ einfach: Auf einem JFrame gibt es einen Button "Drucken". Wenn ich auf diesen Button klicke, so wird von einer sogenantnen PrintService Klasse die "print" Methode aufgerufen. Diese Methode startet einen neuen Thread, und druckt ein Dokument aus.

Nun möchte ich, dass, sobald der Benutzer auf "Drucken" geklickt hat, ein kleines Fenster erscheint, mit dem Hinweis, dass der Druck gerade in Gange sei. Sobald die "print" Methode des "PrintService" fertig ist (oder genauer: der Thread, der von der "print" Methode zum Drucken erzeugt wurde), so soll das Hinweisfenster wieder verschwinden.

Nun weiß ich, dass man per .wait() und .notify() oder seit Java 5 mit await() und signal() z.B. das Ende eines Thread signalisieren kann. Mein Problem ist nun, was mache ich in der GUI Methode, wenn der Benutzer auf "Drucken" geklickt hat. Ich kann ja den Thread nicht einfach mit .wait() anhalten, denn es handelt sich um den Event-Dispatch-Thread, das würde bedeuten, dass die GUI eingefroren ist.

Kann mir jemand sagen, wie man hier vorgeht? Ich möchte auf das Ende eines Thread innerhalb des EDT warten, dabei darf der EDT aber nicht einfrieren.


Ich würde mich über Eure Hilfe sehr freuen


Vielen Dank!
 
Hallo,

schau mal hier:
Java:
/**
 * 
 */
package de.tutorials;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;

/**
 * @author Tom
 * 
 */
public class AsynchronousUIActionExample extends JFrame {

    public AsynchronousUIActionExample() {
        super("AsynchronousUIActionExample");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        final JButton btnPrint = new JButton("print");
        btnPrint.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Executors.newSingleThreadExecutor().execute(new Runnable() {
                    @Override
                    public void run() {
                        btnPrint.setEnabled(false);
                        JFrame printingWindow = new JFrame("PrintStatus "
                                + System.currentTimeMillis());
                        JProgressBar progressBar = new JProgressBar(0, 100);
                        progressBar.setStringPainted(true);
                        printingWindow.add(progressBar);
                        printingWindow
                                .setLocationRelativeTo(AsynchronousUIActionExample.this);
                        printingWindow.pack();
                        printingWindow.setVisible(true);
                        for (int i = 0; i <= 100; i += 10) {
                            try {
                                TimeUnit.SECONDS.sleep(1);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            progressBar.setValue(i);
                        }
                        printingWindow.dispose();
                        btnPrint.setEnabled(true);
                    }
                });
            }

        });
        add(btnPrint, BorderLayout.CENTER);

        JButton btn = new JButton("Test");
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(null, "Still responsive!");
            }
        });
        add(btn, BorderLayout.SOUTH);

        setLocationRelativeTo(null);

        pack();
        setVisible(true);
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        new AsynchronousUIActionExample();
    }

}

Da du hier nur das enablement bzw. die Progresswerte aktualisierst brauchst du dich hier nicht mit dem EDT zu synchronisieren...

Gruß Tom
 
Alternativ kannst du auch den Printthread am Ende eine methode an deinem Printdialog aufrufen lassen.
Wenn du willst auch mit richtigen Events ;).
 
Der SwingWorker scheint wirklich eine sehr schöne Geschichte zu sein.
An mir als Mac User gehen leider die meisten Neuerungen aus Java 6 vorbei, da Apple sich mit der Implementierung der JRE diesmal sehhhr viel Zeit zugesteht.
 
Zurück