ERLEDIGT
NEIN
NEIN
ANTWORTEN
12
12
ZUGRIFFE
1346
1346
EMPFEHLEN
-
Hallo,
ich bastel gerade meine GUI (ich benutze SWT) zusammen. Dort soll während einer langen Berechnung immer eine aktualisierte Statistik mitlaufen, also z.B. ein Zähler, der mitläuft und in einem Textfeld aktualisiert wird usw.
Idealerweise auch mit Graphen, die den Verlauf anzeigen, einem Zähler, der die verstrichene Zeit misst usw.
Sowas hab ich aber noch nie gemacht. Meine Fragen:
- Geht sowas überhaupt mit SWT?
- Was für Klassen nimmt man am besten dafür? Die aus dem org.eclipse.swt.graphics Paket?
Der Kontrollfluss ist ungefähr so:
- Programm startet
- Welt wird erschaffen
- Gui wird erschaffen
- Per Knopfdruck fängt die Welt an wilde Sachen zu machen, die ich auf der Konsole ausgebe
Wie kann ich das jetzt in der GUI ausgeben? Die Welt weiss ja schließlich nichts von der GUI? Muss man sowas generell mit Threads lösen?
Über Tipps würde ich mich sehr freuen.
Gruß,
Joghurt
-
21.09.04 23:50 #2
- Registriert seit
- Aug 2004
- Beiträge
- 96
Du meinst also eine ProgresBar, die den Fortschritt einer Berechnung anzeigt?
http://java.sun.com/docs/books/tutor.../progress.html
google-suche
-
Nein, eigentlich eher eine Verlaufskurve wie z.B. bei Börsenkursen. Geht mal höher, mal niedriger. Und halt die Sache wie ich von berechnenden Objekt aus die GUI aktualisiere.
Ich hab dem Objekt jetzt als Parameter das GUI Objekt mitgegeben und dann soll es jetzt immer eine Methode des GUI Objekts aufrufen, damit dieses sich ändert. Macht man das so?
-
Kann man machen. Flexibler und für größere Projekte geeigneter ist das Listener-Konzept. Zumal wenn die GUI nicht nur aus einem Fenster/Frame besteht und sich Änderungen in der Datenklasse an verschiedenen Stellen auswirken sollen, sprich eine Aktualisierung der Anzeige erforderlich ist.Original geschrieben von Joghurt
Ich hab dem Objekt jetzt als Parameter das GUI Objekt mitgegeben und dann soll es jetzt immer eine Methode des GUI Objekts aufrufen, damit dieses sich ändert. Macht man das so?
-
Erstmal vielen Dank für Eure Hilfe!

Stimmt. Das hört sich logisch an. Aktualisiert werden sollen zwei Text-Objekte und dann halt die Sache mit der mitlaufenden Kurve für die Statistik (aber das ist erstmal nur Zugabe).
Wer kriegt jetzt die Listener? Jedes der beiden Text-Objekte? Eines wird laufend aktualisiert (Zähler), das andere nur von Zeit zu Zeit (aktuell bestes Ergebnis). Oder kriegt das Fenster, in dem sich beide befinden, den Listener?
Die berechnungen laufen in einer Methode der Art
welt.berechne(AusgabeFenster ausgabeFenster){
for (int zaehler=1 ; zaehler<=1000000 ; zaehler++) {
...
[zaehlerTextfeld in der GUI aktualisieren]
[unter best. Umständen ausgabeTextfeld aktualisieren]
}
}
Da muss ich dann Event-Ereignisse erschaffen und an die Text-Objekte übergeben?Geändert von Joghurt (22.09.04 um 11:15 Uhr)
-
Deine beiden Text-Objekte deines JFrame (?) sollen ja reagieren. Also registrierst Du das Frame als Listener bei der Datenklasse. Im einzelnen sieht das z.B. so aus:Original geschrieben von Joghurt
Stimmt. Das hört sich logisch an. Aktualisiert werden sollen zwei Text-Objekte und dann halt die Sache mit der mitlaufenden Kurve für die Statistik (aber das ist erstmal nur Zugabe).
Wer kriegt jetzt die Listener? Jedes der beiden Text-Objekte? Eines wird laufend aktualisiert (Zähler), das andere nur von Zeit zu Zeit (aktuell bestes Ergebnis). Oder kriegt das Fenster, in dem sich beide befinden, den Listener?
Die berechnungen laufen in einer Methode der Art
welt.berechne(AusgabeFenster ausgabeFenster){
for (int zaehler=1 ; zaehler<=1000000 ; zaehler++) {
...
[zaehlerTextfeld in der GUI aktualisieren]
[unter best. Umständen ausgabeTextfeld aktualisieren]
}
}
Da muss ich dann Ereignisse erschaffen und an die Objekte übergeben?
Datenklasse:
- In der Datenklasse legst Du eine ArrayList an, die die Listener beinhaltet, z.B. alListener
- In der Datenklasse implementierst Du eine zugehörige addViewListener(ViewListener l)-Methode und notifyViewListeners()
- In der addViewListener(...) fügst Du den übergebenen ViewListener einfach nur der ArrayList alListener hinzu.
- In der notifyViewListeners() iterierst Du über die ArrayList und lässt jeden einzelnen ViewListener darin die Interface-Methode ausführen (1)
- An den Stellen, an denen sich Daten ändern oder aus sonstigen Gründen die Listener benachrichtigt/aktualisiert werden sollen, rufst Du einfach notifyViewListeners() auf.
(1) Interface
- Leg eine Klasse als Interface an, z.B. ViewListener
- Darin definierst Du Deine Interface-Methode, z.B. fireViewChanged
(2) GUI/Frame:
- Implementiere das Interface ViewListener
- Implementiere die Methode fireViewChanged (MUSS!)
- In der Methode fireViewChanged rufst Du die notwendigen Aktualisierungen der GUI/des Frames auf
- Nun muss nur noch GUI/Frame als Listener der Datenklasse hinzugefügt werden. HIer eignet sich üblicherweise eine Instanz der Datenklasse als Singleton anzulegen und z.B. so aus der GUI hinzuzufügen: MyDataClass.getInstance().addViewListener( this );
Ich hoffe, das ist einigermaßen verständlich, aber so funktionieren Listener. Falls Du noch einen anderen Dialog oder einen anderen Frame aktualisieren möchtest, gehst Du einfach wieder wie in (2) vor, das ist schon alles.
(Ob man das als Tutorial nehmen kann?
Vllt. mit einem einfachen Beispielcode?)
Ah noch was: Unter Umständen ist die Performance nicht so prickelnd, in der Schleife bis 1000000 jedes mal die GUI zu aktualisieren, wirste aber sehen.
-
Wow! Vielen Dank für die ausführliche Antwort. Ich werd mir das mal anschauen und versuchen, es zu verstehen. Evtl. aktualisiere ich die GUI dann eben nur jeden 50. oder 100. Durchlauf.
Ich benutze übrigens keinen JFrame, sondern hab mir sowas zusammengebastelt:
public class Fenster {
protected Shell shell = new Shell();
protected Display display = null;
}
Alle vorkommenden Fenster sind dann Erweiterungen davon, z.B.
public class guiHauptfenster extends Fenster() {
...
}
mit GridLayout, Group, Button und Text-Objekten. Ich weiss jetzt nicht, ob man das so macht, aber es funktioniert...
-
Kann man sicher auch machen, für das Listener-Konzept ist das allerdings egal.
-
Soweit klappt alles ganz gut. Nur einen Haken hat die Sache:
die Methode fireZaehlerAktualisieren() wird im Daten-Objekt der Weltklasse (mittlerweile Singleton) korrekt aufgerufen. Das hab ich per Ausgabe überprüft. Allerdings wird die GUI nur 1x geändert bzw. die Änderung sichtbar und zwar genau am Ende des Programms.
final Label zaehlerText = new Label(gruppeZaehler, SWT.WRAP);
public void setZaehler(String string) {
zaehlerText.setText(string);
zaehlerText.pack();
}
public void fireZaehlerAktualisieren(){
int zufallszahl = MatheFunktionen.zufallsInt(1,100);
String string = ""+zufallszahl;
this.setZaehler(string);
System.out.println("fireZaehlerAktualisieren aufgerufen: "+ zufallszahl);
}
-
Scheint wohl an der schlecht realisierten VM von Mac OS X zu liegen. Auf meinem Windows Rechner läuft es. Echt zum kotzen, wie stiefmütterlich Java für alle nicht Win-Systeme behandelt wird. War unter Linux ähnlich träge...
-
Bei Problemen mit der Aktualisierung hilft oftmals ein repaint().Original geschrieben von Joghurt
Soweit klappt alles ganz gut. Nur einen Haken hat die Sache:
die Methode fireZaehlerAktualisieren() wird im Daten-Objekt der Weltklasse (mittlerweile Singleton) korrekt aufgerufen. Das hab ich per Ausgabe überprüft. Allerdings wird die GUI nur 1x geändert bzw. die Änderung sichtbar und zwar genau am Ende des Programms.
Code :1 2 3 4 5 6
public void fireZaehlerAktualisieren(){ int zufallszahl = MatheFunktionen.zufallsInt(1,100); String string = ""+zufallszahl; this.setZaehler(string); System.out.println("fireZaehlerAktualisieren aufgerufen: "+ zufallszahl); }
-
Halli hallo,
Zitat von Joghurt
das Problem, dass das GUI sich nicht aktualisiert liegt nicht selten daran, das man seine Berechnungen in den Thread gelegt hat, in dem das System seine GUI-Anforderungen (Events) verarbeitet. Ich weiß nicht wie es in Eclipse genannt wird und welche Routinen man da verwenden muß, aber in Swing gibt es da 2 Methoden
1) SwingUtilities.invokeLater(Runable);
2) SwingUtilities.invokeAndWait(Runable);
In anderen Worten, man lässt seine Berechnungen, so sie lange dauern, in einen extra Thread ablaufen und ruft daraus eine der obigen Routinen auf um damit das GUI zu verändern.
Dem zufolge sollten die Änderungen als Runable definiert werden.
Du mußt mal, falls Eclipse ähnliches bereithält, natürlich die equivalenten Routinen suchen/finden/anwenden.
In der Hoffnung der Tip hilft,
Takidoso
-
23.11.04 23:23 #13
- Registriert seit
- Jun 2002
- Ort
- Saarbrücken (Saarland)
- Beiträge
- 9.886
- Blog-Einträge
- 29
Hallo!
Schau dir doch mal die Methoden:
syncExec(Runnable runnable)
Causes the run() method of the runnable to be invoked by the user-interface thread at the next reasonable opportunity.
und
asyncExec(Runnable runnable)
Causes the run() method of the runnable to be invoked by the user-interface thread at the next reasonable opportunity.
der Klasse: org.eclipse.swt.widgets.Display
an.
Gruß TomJava rocks!
How to become a good Java Programmer?
Does IT in Java and .Net
The only valid measurement of code quality: WTFs / minute
Blog
Xing
Twitter
Ähnliche Themen
-
Ausgabe von Datensätzen als Tabelle, Ausgabe horizontal statt vertikal
Von godfather_al im Forum PHPAntworten: 15Letzter Beitrag: 16.08.09, 22:31 -
Ausgabe in cmd-Fenster statt Konsole
Von Ashaman im Forum Java GrundlagenAntworten: 5Letzter Beitrag: 01.07.08, 15:03 -
Textarea statt Konsole!
Von Ramix im Forum JavaAntworten: 3Letzter Beitrag: 20.12.07, 21:17 -
Hilfe! û statt - in der Konsole!
Von athlon im Forum Microsoft WindowsAntworten: 2Letzter Beitrag: 27.09.05, 19:53 -
Ausgaben von SELECT in Datei statt auf Konsole
Von MichiM im Forum Relationale DatenbanksystemeAntworten: 3Letzter Beitrag: 18.08.04, 18:07





Zitieren

Login





