ProgressBar, Job, SWT

Hallo,

ich habe eine GUI (SWT) in der eine ProgressBar angezeigt werden soll.

Da das ja nicht geht, wenn die GUI auf irgendwas warten muss, muss die eigentlich Aufgabenbearbeitung ja als Thread ausgelagert werden…

In meinem Fall ist dies eine Methode die ein Objekt zurück gibt.

Wenn ich das jetzt als Thread starte, macht der andere ja erstmal weiter und das Objekt ist also null und die GUI hat nix zum anzeigen.

Also muss ich ja irgendwie vom JobThread gesagt bekommen: „ich bin fertig“.

Und jetzt die Frage: Wie geht das? Gibts da irgend eine Job-Klasse mit Event, wenn sie fertig ist?

Danke

Dario

… vielleicht gehe ich da auch ganz falsch ran, in diesem Fall, vielleicht ein paar Worte um mich in die richtige Richtung zu stoßen?

… vielleicht gehe ich da auch ganz falsch ran, in diesem
Fall, vielleicht ein paar Worte um mich in die richtige
Richtung zu stoßen?

Hey.

Klingt für mich nach einem klassischen SwingWorker-Problem. Google mal danach; darüber gibt es bestimmt genug Inhalte.
Kurz: Der SwingWorker sorgt dafür, dass deine GUI-Anwendung weiterhin bedienbar bleibt während er - asynchron - einen Job ausführt.

Viel Erfolg,
Chris

Hallo,

Klingt für mich nach einem klassischen SwingWorker-Problem.

Mit Swing würde man die statische Methode

EventQueue.invokeLater(new Runnable() {
 public void run() {
 ...
 }
 }
 )

aufrufen, um einen Thread zu starten, der auf Swing-Elemente zugreift.

Mit SWT ist das etwas anders. Hier braucht man das aktuelle
Display

display.syncExec(new Runnable() {
 public void run(){
 ...;
 }
 }
 ); 

um einen Thread zu starten, der auf ein UI-Element zugreift.
Ein Link dazu:
http://java.sys-con.com/read/37509.htm
unter der Überschrift „Multithreaded Programmming“.

HTH
Torsten

1 Like

Hallo,

noch eine Berichtigung zum vorher Geschriebenen:

der SWING-Methode EventQueue.invokeLater entspricht die SWT-Methode display.asyncExec.
Diese beiden warten nicht, bis die run-Methode abgearbeitet ist,
während EventQueue.invokeLaterAndWait bzw. display.syncExec den aufrufenden Thread solange anhalten, bis die run-Methode fertig ist.

Gruß
Torsten

Hallo,

jetzt hab ich das nochmal probiert. Habe einfach mal eine ProgressBar angezeigt, die immer durchläuft und folgendes Runnable gestartet:

this.display.syncExec(new Runnable() {
public void run() {
processInternal(finalRequest, finalClient);
}
});

Wenn ich das starte bleibt die ProgessBar stehen und die GUI hängt.

Wenn ich das gleiche mit asyncExec mache, geht die Verarbeitung der Ergebnisse los, bevor ein Ergebnis der Methode in run() vorliegt.

Was mache ich verkehrt?

Hallo Seawulf,

du brauchst zwei Threads: einen, der rechnet und einen, der die Anzeige aktualisiert:

public void berechnen(){ 
 Runnable Berechnung = new Runnable(){ 
 public void run(){ 
 for (int i=0;i

Gruß
Torsten

Hallo Torsten,

basierend auf deinem Vorschlag habe ich jetzt mal eine Test-Klasse geschrieben. Allerdings noch immer mit dem gleichen Ergebnis: GUI hält an bis die Berechnung fertig ist.

Hier die Klasse (mit sinnloser Berechnung, was aber egal ist):

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;

/**
*
* Klasse zum Test der ProgressBar-Funktionalität
*
*/
public class ProgressTest {

Display display;

private Shell shell;

Composite upComposite;

Composite downComposite;

ProgressBar pb;

ProgressBar pb2;

Label label;

/**
*
*/
public ProgressTest() {
this.display = new Display();
this.shell = new Shell();
this.shell.setText(„ProgressTest“);
this.shell.setSize(400, 200);
createGUI();
this.shell.open();
while (!this.shell.isDisposed()) {
if (!this.display.readAndDispatch())
this.display.sleep();
}
}

private void createGUI() {
this.shell.setLayout(new GridLayout());

/**
* oben
*/
this.upComposite = new Composite(this.shell, SWT.BORDER);
this.upComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
this.upComposite.setLayout(new GridLayout(1, false));

Button goButton = new Button(this.upComposite, SWT.FLAT);
goButton.setText(„GO“);
goButton.setLayoutData(new GridData(80, 20));
goButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent arg0) {
process_go();
}
});
this.pb = new ProgressBar(this.upComposite, SWT.SMOOTH);
this.pb.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
this.pb.setMaximum(100);
this.pb.setMinimum(0);

this.pb2 = new ProgressBar(this.upComposite, SWT.SMOOTH
| SWT.INDETERMINATE);
this.pb2.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
/**
* unten
*/
this.downComposite = new Composite(this.shell, SWT.BORDER);
this.downComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
this.downComposite.setLayout(new GridLayout(1, false));

this.label = new Label(this.downComposite, SWT.NONE);
this.label.setLayoutData(new GridData(GridData.FILL_BOTH));
this.label.setText(„press „GO“ to start“);
}

protected void process_go() {
this.label.setText("…");
double summe = berechnen();
this.label.setText("Summe: " + Math.round(summe));
}

/**
* @return int
*
*/
public double berechnen() {
Berechnung myBerechnung = new Berechnung(this);
this.display.syncExec(myBerechnung);
return myBerechnung.getSum();
}

/**
* @param value
*/
public void neueAnzeige(final int value) {
this.display.asyncExec(new Runnable() {
public void run() {
ProgressTest.this.pb.setSelection(value);
}
});

}

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

/**
*
* Berechnung: Runnable
*
*/
class Berechnung implements Runnable {

private ProgressTest myTest;

private double sum = 1;

/**
*
* @param myTest
*/
public Berechnung(ProgressTest myTest) {
this.myTest = myTest;
}

public void run() {
for (int i = 0; i