Auf Swingworker warten?

Thallius

Top Contributor
Hi,

Ich habe folgendes Konstrukt.

Es gibt eine Klasse, nennen wir sie Daten, welche Daten aus dem Internet läd was ja bekanntlich schonmal länger dauern kann. Diese Klasse wird von vielen verschiedenen Stellen meiner App aufgerufen. Die Aufrufende Methode möchte eigentlich nur folgendes machen

Java:
Daten daten = new Daten();
if(daten.load()==false)
     mache irgendwas
sonst mache was anderes.

So nun muss ja in der load() Methode des Klasse Daten aber irgendwie ein Langzeit-Requester mit Abbruch Button geöffnet werden.

Das ist ja auch kein Problem. Ich erzeuge im einfachsten Fall ein Panel mit einem ProgressIndicator und einem AbbruchButton und lasse die Klasse Daten über eine Methode dialogDidCancel() davon erfahren wenn der CancelButton gedrückt wurde.
Dann erzeuge ich einen SwingWorker und lasse im Background die Daten laden. Soweit so gut.
Aber nachdem ich das Panel aufgemacht habe und dem Worker ein execute() geschickt habe, kommt ja meine Load() Methode erstmal wieder zur aufrufenden Methode zurück. Das will ich aber ja nicht. Ich müßte also quasi in der load() MEthode warten bis der Worker fertig ist. Mache ich das aber mit z.B.

Java:
while(!worker.isDone())
    Thread.sleep(250)

was ich eh schon häßlich finde, dann ist aber natürlich auch der Thread blocked und der Dialog wird nicht gezeichnet.

Erkennt ihr mein Dilemma? Wie mache ich sowas richtig?

Danke

Claus
 

Foxei

Bekanntes Mitglied
Hallo Thallius,
es ist relativ simple als beispiel du hast Klasse B in der Die Datein mit einem Swing worker geladen werden. Und in Klasse A soll etwas passieren wenn der Worker fertig ist. Dann Legen wir in der Klasse A eine Methode an in der alles Steht was passieren soll nach dem der Worker aus B fertig ist. Dann übergeben wir dem Worker aus Klasse B die Klasse A und Overriten die done() im SwingWorker(wird zum Schluss im Worker ausgeführt) darun Rufen wir die vorher angelegte Methode X aus Klasse A auf und Fertig.

Gruß Simon
 

Thallius

Top Contributor
Ja so mache ich es ja im Moment aber es ist halt ätzend weil Das was der worker macht ja nicht nur aus Klasse A aufgerufen wird sonder auch aus Klasse B und C und ...
Das bedeutet ich muss in jeder dieser Klassen diesen Konstrukt aufbauen und vor allem muss ich dem worker dann klarmachen, das die Methode die er aufrufen soll wenn er fertig ist ins verschiedenen Klassen sein kann. Also muss ich da wohl mit irgendwelchen interfaces arbeiten. Das bauscht die Sache ja toral auf.
Ich dachte das müsste doch eigentlich auch irgendwie einfacher gehen ohne das ich eine Verbindung zwischen den Klassen herstellen muss

Gruß

Claus
 
Zuletzt bearbeitet:

X5-599

Top Contributor
Was hälst du von folgendem Konstrukt. Also, wenn ich dich richtig verstanden habe soll die load() Methode blocken. Dann müsstest du die ja per neuem Thread starten, damit der EDT nicht auch blockiert wird. Das wäre die Daten Klasse:
Java:
package test.background;

import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class Daten
{
	private JDialog dialog;
	private SwingWorker<Void, Void> w;
	
	public Daten(Component parent)
	{
		JPanel innerPanel = new JPanel(new GridLayout(2, 1));
		JProgressBar progressBar = new JProgressBar();
		progressBar.setIndeterminate(true);
		innerPanel.add(progressBar);
		
		JButton cancel = new JButton("cancel");
		cancel.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e)
			{
				w.cancel(true);
			}
		});
		innerPanel.add(cancel);
		
		
		dialog = new JDialog();
		dialog.setTitle("Worker Dialog");
		dialog.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e)
			{
				w.cancel(true);
			}
		});
		dialog.setSize(340, 75);
		dialog.setLocationRelativeTo(parent);
		dialog.add(innerPanel);
	}
	
	private void showDialog()
	{
		SwingUtilities.invokeLater(new Runnable() {
			
			@Override
			public void run()
			{
				dialog.setVisible(true);
			}
			
		});
	}
	
	private void closeDialog()
	{
		SwingUtilities.invokeLater(new Runnable() {
			
			@Override
			public void run()
			{
				dialog.dispose();
			}
			
		});
	}
	
	public boolean load()
	{
		showDialog();
		
		w = new SwingWorker<Void, Void>() {
			
			@Override
			protected Void doInBackground() throws Exception
			{
				System.out.println("simulate working...");
				Thread.sleep(10000);
				System.out.println("simulate working done.");
				return null;
			}
			
			@Override
			protected void done()
			{
				closeDialog();
			}
		};
		
		
		try
		{
			w.execute();
			w.get();
			return true;
		}
		catch(CancellationException e)
		{
			//Läuft hier rein, wenn cancel gewählt wird
			return false;
		}
		catch(InterruptedException e)
		{
			//Läuft hier rein, wenn interrupt while waiting?
			e.printStackTrace();
			return false;
		}
		catch(ExecutionException e)
		{
			//Läuft hier rein, wenn eine Exception in doBackground() auftritt
			e.printStackTrace();
			return false;
		}
	}
	
}


BackgroundTest

Java:
package test.background;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class BackgroundTest
{
	
	public static void main(String[] args)
	{
		SwingUtilities.invokeLater(new Runnable() {
			
			@Override
			public void run()
			{
				final JFrame frame = new JFrame("Test Frame");
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.setSize(200, 200);
				frame.setLocationRelativeTo(null);
				
				JPanel panel = new JPanel();
				JButton b = new JButton("Go");
				b.addActionListener(new ActionListener() {
					
					@Override
					public void actionPerformed(ActionEvent e)
					{
						Thread t = new Thread() {
							@Override
							public void run()
							{
								Daten daten = new Daten(frame);
								if(daten.load())
								{
									System.out.println("load came back true");
								}
								else
								{
									System.out.println("load came back false");
								}
							}
						};
						t.start();
					}
				});
				panel.add(b);
				
				frame.add(panel, BorderLayout.CENTER);
				frame.setVisible(true);
			}
			
		});
	}
	
}

Gleichzeitiges Verwenden eines Objektes der Daten Klasse aus mehreren Threads wäre so natürlich nicht möglich. Der SwingWorker würde immer durch einen neuen ersetzt und da es nur einen Dialog gibt, wird der erste SwingWorker der fertig wird diesen beenden. Theoretisch zumindest. Ob ein SwingWorker, der keine Referenz mehr hat, aus dem Nirvana noch das dispose auf dem Dialog aufrufen kann bevor er von Garbage Collector abgeräumt wird... Keine Ahnung.
 

Tom299

Bekanntes Mitglied
Ich benutz zwar kein Swing mehr, aber in JavaFX funktioniert das gute, alte Listener-Prinzip auch noch ohne Probleme:

Deine Datenklasse (hier Reader) erbt von Thread und hält eine Liste vom gewünschten Interface-Typ und ruft dann je nachdem, was in der Datenklasse passiert, die entsprechende Methode des Interfaces auf. Deine Klasse, welche auf die Daten wartet, implementiert das Interface und bekommt dann die Daten, sobald sie vorliegen. Für mich war das immer schon die einfachste Variante, mit Threads umzugehen und meiner Meinung nach auch gut verständlich. Man hat alles selbst in der Hand und weiß, was passiert.

Beispiel:

Interface
Code:
package de.test;

public interface IReader {
	
	public void loaded(Object data);
	public void canceled(Object error);
	
}

Reader
Code:
package de.test;

import java.util.ArrayList;

public class Reader extends Thread {

	private ArrayList<IReader> listener;
	
	public Reader() {
		listener = new ArrayList<IReader>(0);
	}
	
	@Override
	public void run() {
		try {
			Thread.sleep(3000);
			ArrayList<String> data = new ArrayList<String>(0);
			data.add("AAA");
			data.add("BBB");
			data.add("CCC");
			
			for (IReader reader : listener) {
				reader.loaded(data);
			}
		}
		catch (InterruptedException ie) {
			for (IReader reader : listener) {
				reader.canceled(ie);
			}
		}
	}
	
	public void addListener(IReader reader) {
		listener.add(reader);
	}
}

Testklasse implements IReader
Code:
	public void buttonAction(ActionEvent event) {
		if (event.getSource().equals(btnTest)) {
			System.out.println("Button clicked ...");
			
			Reader r = new Reader();
			r.addListener(this);
			r.start();
			//r.interrupt();
		}
	}
	
	@Override
	public void loaded(Object data) {
		if (data != null) {			
			ArrayList<String> list = (ArrayList<String>)data;
			for (String s : list) {
				System.out.println(s);
			}
		}
	}
	
	@Override
	public void canceled(Object error) {
		if (error != null) {
			InterruptedException ie = (InterruptedException)error;
			System.out.println(ie.getMessage());
		}
	}

Über das Interface kannst du dann deine gewünschten Methoden implementieren, z.B. progress(int) für deine Progressbar oder ganz nach Belieben was immer dir so einfällt.
 

Thallius

Top Contributor
Danke,

ja so hab ich es jetzt auch gemacht. Ist halt schon etwas umständlich, wenn man von C++ kommt, wo man einfach einen beliebigen Funcpointer als Callback angeben kann und gut ist.

Gruß

Claus
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
C Swing SwingWorker: Auf beendigung eines Formulars / einer Arbeit warten AWT, Swing, JavaFX & SWT 10
ralfb1105 Swing Frage zu SwingWorker Verhalten bei cancel() AWT, Swing, JavaFX & SWT 2
ralfb1105 Swing SwingWorker - max 10 Threats werden gestartet !? AWT, Swing, JavaFX & SWT 5
ralfb1105 Swing Ausführung einer SwingWorker Klasse stoppen AWT, Swing, JavaFX & SWT 4
ralfb1105 Swing Timer in SwingWorker stoppen AWT, Swing, JavaFX & SWT 4
S Swing SwingWorker - richtige Implementierung doInBackground() AWT, Swing, JavaFX & SWT 5
H Swing BufferedReader.close() hängt im SwingWorker AWT, Swing, JavaFX & SWT 1
Nuiton Swing SwingWorker - Prozess stoppen AWT, Swing, JavaFX & SWT 4
M SwingWorker Hilfe! AWT, Swing, JavaFX & SWT 10
J Swing Nach SwingWorker Funktion aus der GUI Klasse aufrufen AWT, Swing, JavaFX & SWT 5
C Swing SwingWorker abbrechen AWT, Swing, JavaFX & SWT 12
Psypsy Swing SwingWorker unterschied zwischen setProgress und process AWT, Swing, JavaFX & SWT 2
A Swingworker rückgabewert verwenden AWT, Swing, JavaFX & SWT 9
B Frage zu Swing,Threads, SwingWorker und Socket Communikation AWT, Swing, JavaFX & SWT 4
M Prioritäten bei SwingWorker / Threads AWT, Swing, JavaFX & SWT 9
M Liste mittels SwingWorker füllen klappt nicht AWT, Swing, JavaFX & SWT 10
Iron Monkey SwingWorker verschwindet nicht AWT, Swing, JavaFX & SWT 10
X Prozess mit Runtime.getRuntime in SwingWorker aufrufen AWT, Swing, JavaFX & SWT 6
R Zugriff auf Model im MVC-Design aus SwingWorker heraus AWT, Swing, JavaFX & SWT 3
G SwingWorker setProgress Problem AWT, Swing, JavaFX & SWT 17
K Frage zu ProgressBar, SwingWorker etc. AWT, Swing, JavaFX & SWT 4
G SwingWorker AWT, Swing, JavaFX & SWT 2
J Unterschied zwischen SwingWorker und Threads AWT, Swing, JavaFX & SWT 4
S SwingWorker :( AWT, Swing, JavaFX & SWT 6
F swingworker und eventdispatch thread AWT, Swing, JavaFX & SWT 9
S SwingWorker - ich werde wahnsinnig AWT, Swing, JavaFX & SWT 4
0 SwingWorker Tutorial ? AWT, Swing, JavaFX & SWT 2
L SwingWorker Thread pausieren AWT, Swing, JavaFX & SWT 12
L SwingWorker Statusabfrage AWT, Swing, JavaFX & SWT 8
M Kann ein SwingWorker nur einmal laufen? AWT, Swing, JavaFX & SWT 2
J SwingWorker, get und boolean AWT, Swing, JavaFX & SWT 6
izoards JavaFX Background Task warten auf Knopfdruck AWT, Swing, JavaFX & SWT 4
G FX warten bis ein anderes GUI Element ausgewählt wurde AWT, Swing, JavaFX & SWT 8
SvenPittelkow Programm soll auf JButton warten bis der geklickt wurde AWT, Swing, JavaFX & SWT 1
kodela Swing Anzeige des Warten-Cursors AWT, Swing, JavaFX & SWT 8
H Eigener Dialog mit Rückgabe -> Warten auf Button AWT, Swing, JavaFX & SWT 3
kodela Swing Problem mit Warten-Dialog AWT, Swing, JavaFX & SWT 16
J Compiler in der JavaFX stop() Methode warten lassen bist eine Aktion in einer anderen Scene gemacht AWT, Swing, JavaFX & SWT 5
W JavaFX Webview warten bis Seite geladen geladen ? AWT, Swing, JavaFX & SWT 0
U Java FX Warten auf Textfield eingabe AWT, Swing, JavaFX & SWT 17
M JavaFX FadeTransition, warten bis beendet AWT, Swing, JavaFX & SWT 10
O Swing JDialog öffnen und dann warten bis er geschlossen wurde AWT, Swing, JavaFX & SWT 2
H Event Handling JavaFx - auf Event warten AWT, Swing, JavaFX & SWT 4
D Swing Bei MenuSelectionManager auf Ausführung warten? AWT, Swing, JavaFX & SWT 5
gamebreiti auf usereingabe warten mit GUI(nur Labels, Buttons etc. keine Texteingaben) AWT, Swing, JavaFX & SWT 3
P Warten auf komponente AWT, Swing, JavaFX & SWT 2
H AWT Auf Bestätigung warten AWT, Swing, JavaFX & SWT 6
B Timer, TimerTask und Warten AWT, Swing, JavaFX & SWT 4
L JavaFX Wait/Sleep/postedDelay - Einfach nur warten AWT, Swing, JavaFX & SWT 4
F JFrame nach Buttonklick 3 Sekunden warten, bevor es sich ändert AWT, Swing, JavaFX & SWT 2
C Schleife auf Mausklick warten lassen AWT, Swing, JavaFX & SWT 6
A Auf Tastendruck warten AWT, Swing, JavaFX & SWT 9
A Auf eingabe warten AWT, Swing, JavaFX & SWT 5
S auf paintComponent() warten AWT, Swing, JavaFX & SWT 34
B Warten bis neues ImageIcon zugewiesen ist AWT, Swing, JavaFX & SWT 3
S Swing Bild (Gif) in Bitte warten JDialog AWT, Swing, JavaFX & SWT 6
K Vom Gui aus auf einen Thread warten AWT, Swing, JavaFX & SWT 4
M Hauptprogramm pausieren und auf Ergebnis eines JDialogs warten AWT, Swing, JavaFX & SWT 7
I Swing Warten, bis eine GUI-Komponente aktualisiert ist? AWT, Swing, JavaFX & SWT 4
A Swing Warten bis JDialog fertig AWT, Swing, JavaFX & SWT 3
T Auf Ende von mehreren Threads warten, ohne den EDT zu blockieren AWT, Swing, JavaFX & SWT 1
pinerski Swing Frame 1 soll auf Frame 2 warten AWT, Swing, JavaFX & SWT 4
0x7F800000 Allg. Frage zum ev. dispatch thread, wie korrekt auf reaktion der Listener warten? AWT, Swing, JavaFX & SWT 4
R JDialog "Bitte warten..." durchsichtig AWT, Swing, JavaFX & SWT 5
G JTable warten bis Spalte verschoben wurde AWT, Swing, JavaFX & SWT 2
C Warten auf Rückgabewert im EventDispatchingThread AWT, Swing, JavaFX & SWT 8
A Bitte warten Dialog AWT, Swing, JavaFX & SWT 4
G Auf Ergebnis vom Thread warten AWT, Swing, JavaFX & SWT 3
O Zwei Listener auf Komponente, warten auf Beendigun? AWT, Swing, JavaFX & SWT 2
R Warten auf Ergebnisse eines untergeordneten JFrame AWT, Swing, JavaFX & SWT 2
C Auf Ereignis warten AWT, Swing, JavaFX & SWT 7
L Warten, aber trotzdem "lebende" UI AWT, Swing, JavaFX & SWT 2
K Textfeld Programm soll auf Eingabe warten! AWT, Swing, JavaFX & SWT 4
B Auf Frame/Dialog warten AWT, Swing, JavaFX & SWT 2
A Programmunterbrechung und warten auf Benutzereingabe AWT, Swing, JavaFX & SWT 6
J Warten auf einen Dialog? AWT, Swing, JavaFX & SWT 2
J Programm warten, bis GUI geschlossen ist AWT, Swing, JavaFX & SWT 4
F Auf Thread warten ohne alles andere zu blockieren AWT, Swing, JavaFX & SWT 5
W Auf eine Eingabe warten? AWT, Swing, JavaFX & SWT 2
N malen => 1 Sekunde warten => malen AWT, Swing, JavaFX & SWT 2
m@nu Dialog während warten anzeigen AWT, Swing, JavaFX & SWT 3
U Auf Swings Reaktion warten AWT, Swing, JavaFX & SWT 3
C JFrame warten lassen AWT, Swing, JavaFX & SWT 11

Ähnliche Java Themen

Neue Themen


Oben