Eigener Java Listener zum Aktualisieren von Werten in einer GUI

Nrýgor-Cregath

Grünschnabel
Hallo,

ich möchte mir einen eigenen Listener in JAVA schreiben mit dem ich verschiedene Werte meiner Swing GUI, die in JTextFields angezeigt werden
aktualisieren kann.

Einer dieser Werte könnte z.B. ein Counter sein, der während der Bearbeitung von Dateien mitzählt wie viele Dateien schon bearbeitet wurden.
Ich möchte das die GUI während das Programm läuft immer aktuell anzeigt wieviele Dateien schon bearbeitet wurden und zwar ohne das ich jedesmal einen Button drücken muss
um die Counteranzeige zu aktualisieren. Die Klasse die den Counter erhöht muss doch irgendwie die GUI benachrichtigen können, dass es neue Werte gibt. Ich möchte nicht das Observer-Pattern verwenden, sondern einen eigenen Listener schreiben.

Ich suche schon seit 1-2 Tagen ein Tutorial das mir dabei hilft, mir das nötige Wissen anzueignen um dieses Problem zu lösen. Leider sind alle Anleitungen usw. die ich bisher gefunden habe, eher kurz gehalten und zeigen nur grob wie ich vorgehen muss.

Kurz gesagt, ich schaffe es nicht daraus abzuleiten wie ich von Anfang bis Ende vorgehen muss, welche Klassen und Interfaces ich brauche und was von wo gestartet werden muss.

Mir ist z.B. überhaupt nicht klar wie ich meinem Integer Wert "counter" in einen Listener bekomme, ob ich jedesmal einen neuen Listener adden muss, wenn der counter erhöht wurde, wann ich den Listener removen muss, und wie es vorsich geht dass die Listener Methode die von der GUI implementiert wird die Listener Methode z.B: neuesErgebnis(Ergebnis erg) aufruft.

Sonst bei Swing registriert man ja z.B. wenn man einen ActionListener hat diesen bei einem Button und so wird die actionperformedMethode aufgerufen, aber ich möchte ja keinen Button sondern das die berechnende Klasse Werte während des Laufens ohne einen Button automatisch aktualisiert.

Kann mir jemand helfen?
 
Zuletzt bearbeitet:
Du schreibst eine Methode in ein Interface, lässt es vom Ziel implementieren, gibst dem Thread, der die Klasse zum erhöhen des Counters benutzt die Instance des Ziels, und rufst nach jeder Erhöhung des Counters die Methode auf.
 
Ich mache schnell mal nen "Listener" der jede Sekunde aufgerufen wird.

Zuerst brauchst du natürlich mal das Interface um zu garantieren, dass die Methode existiert.
bgh4x6kt9hwlujsxm.png


Dann brauchst du noch eine Klasse, die das Interface existiert, und deshalb natürlich die Methode implementiert.
bgh4xvm45graekqwq.png


Dann natürlich noch eine, dies Steuert (in deinen Fall das Updaten):

Java:
package core;

import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

class SecondCaller implements Runnable
{
	private boolean terminate;
	private List<SecondListener> listeners;
	
	SecondCaller()
	{
		super();
		listeners = new ArrayList<SecondListener>();
	}
	public void run()
	{
		terminate = false;
		
		do
		{
			try
			{
				TimeUnit.SECONDS.sleep(1L);
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
			
			for(int i = 0, size = listeners.size(); i < size; i++)
				listeners.get(i).second();
		}
		while(!terminate);
	}
	public void addSecondListener(SecondListener listener)
	{
		listeners.add(listener);
	}
	public void start()
	{
		Executors.newFixedThreadPool(1).submit(this);
	}
	public void stop()
	{
		terminate = true;
	}
}

Und dann natürlich noch dem Start:
bgh4ygjj3yl3spqnu.png
 
Super! Danke für das ausführliche Beispiel!

Statt dem "System.out.println("Sekunde um");" könnte ich jetzt ja z.B. auch sowas machen? Oder?

Code:
//in der ListenerClass, wenn diese ein Swingfenster ist
public void Second(Result result){
    jtextfield.setText(result.getCounterIntegerWert + "");
}

Oder muss ich bei einem Swingfenster etwas anders machen. Weil ich möchte ja, dass Werte, wie der Counter in der GUI immer aktuell in einem JTextField angezeigt werden.

Also counter = 1,2,3,4,5,6,7,8,9,...
 
Zuletzt bearbeitet:
Klar. Pass aber auf, ArrayLists sind nicht Thread-Safe, also bei unsyncronen IO-Zugriff kann eine Exception fliegen.
Ist ja Sinn der Listeners. Er bekomme ein Interface und ruft immer wenn was passiert die Methode auf.
 
Klar. Pass aber auf, ArrayLists sind nicht Thread-Safe, also bei unsyncronen IO-Zugriff kann eine Exception fliegen.
Ist ja Sinn der Listeners. Er bekomme ein Interface und ruft immer wenn was passiert die Methode auf.

Ich muss also aufpassen, das alles syncron abläuft? Oder kann ich statt ner ArrayList eine andere Collection verwenden? Mein Programm kann man z.B. auch mit mehreren Threads arbeiten lassen. Ist das problematisch?
 
Zuletzt bearbeitet:
Nein, Ja, Nein.
Es ging nur um dem Zugriff. Die List dient ja nur zum Speichern der Interface, du könntest genauso gut ein Array, ein HashSet (was vielleicht besser wäre) oder etwas vom Typ des Interfaces verwenden, falls du nur eins gleichzeitig brauchst. Nur mir sind schon wärend ich auf eine ArrayList mit get() zugegriffen habe bei einen add() Exceptions geflogen.
 
Hm jetzt habe ich nochmal ne blöde Frage.

Ich starte mein Programm über einen Button in meiner GUI. Dabei werden die Konfigurationsdaten an eine Bibliothek weitergereicht und diese wird dann gestartet. Diese arbeitet Daten ab und gibt mir regelmäßig Werte zurück, wie z.B. soviele Dokumente habe ich schon bearbeitet, soviele sind noch in einer Queue und werden noch bearbeitet, soviele davon sind html Seiten, soviele davon sind Word Dokumente usw. Diese Werte möchte ich jetzt wieder an die GUI, von der aus ich das Programm gestartet habe hochgeben so das dort immer in den jeweiligen jTextFields angezeigt werden kann im augenblick wurden schon 12 Dateien bearbeitet, 40 sind noch in der Queue und 6 von den schon bearbeiteten waren pdfs, 3 Htmlseiten und 3 Worddokumente.

Geht das überhaupt mit dem bisher besprochenen Ansatz? In der QUI gibt es auch eine JTextArea die Werte anzeigt, die über einen Printstream kommen. So eine Art Logfenster. Wird das ganze GUI Fenster neu aufgebaut, wenn ich über die CallerMethode immer die

public void Second(Result result){
jtextfield.setText(result.getCounterIntegerWert + "");
}

Methode aktualisiere? Wenn ja dann hat das bestimmt auswirkungen auf diese Loganzeige. Funktioniert das aktualiseren regelmäßig solange mein Programm läuft?


Und vor allem, muss ich dann eine Instanz genau der GUI Methode von der ich alles gestartet habe runterreichen zum SecondCaller?
 
Zuletzt bearbeitet:
Zurück