Event Handling Ladezeit visualisieren

Babu

Mitglied
Hallo Leute,

ich sitze schon seit einer Weile vor folgendem Problem:
Ich möchte per Button eine Hilfsfunktion ausführen, während diese Hilfsfunktion läuft, soll ein gegebenes JTextArea seinen Inhalt laufend ändern. Das Problem ist, dass es erst am Ende auf einmal aktualisiert wird, was ich nicht verstehe.
Hier mal der Code:
Java:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;

public class Oberflaeche implements Runnable{

	JFrame fenster;
	JTextArea area;
	JButton b = new JButton();
	
	public Oberflaeche(){
		fenster = new JFrame("Test");
		fenster.setSize(new Dimension(300,300));
		fenster.setVisible(true);
		fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		fenster.setLayout(null);
		
		area = new JTextArea();
        area.setBounds(0, 0, 50, 200);
        fenster.add(area);
        
        b = new JButton("test");
        b.setBounds(100, 100, 100, 50);
        fenster.add(b);
		b.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				draw();
			}
		});

        Thread t = new Thread(this);
        t.start();
	}
	
	public void draw(){
		for(int i=0; i<5; i++){
        	area.append(i+"\n");
        	try {Thread.sleep(1000);} 
			catch (InterruptedException e) {}
        }
	}
	
	public static void main(String[] args) {
		Oberflaeche test = new Oberflaeche();
	}

	public void run() {
		while(true){
			fenster.repaint();
			try {Thread.sleep(50);} 
			catch (InterruptedException e) {}
		}
	}
}

Das ist nun nicht mein original Quelltext, verdeutlicht aber das Problem.
Ich weiß nicht wie ich es nun lösen soll, s.d. die Zahlen nacheinander ausgegeben werden.

Aus Tests weiß ich, dass wenn ich die for-Schleife in den Konstruktor von Oberfläche einfüge, die Ausgabe richtig erscheint. Nur will ich die ja erst per Button-klick erzeugen.

Weder im Netz, noch im Forum bin ich fündig geworden.
Wäre euch sehr dankbar, wenn ihr mir den einen oder anderen Ratschlag geben könntet.
 

knilch

Bekanntes Mitglied
Hi,
Hier mal ein Beispiel:
Java:
package plan.com.guiTest;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;

public class Oberflaeche {

	JFrame fenster;
	JTextArea area;
	JButton b = new JButton();

	public Oberflaeche(){
		fenster = new JFrame("Test");
		fenster.setSize(new Dimension(300,300));
		fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		fenster.setLayout(null);

		area = new JTextArea();
		area.setBounds(0, 0, 50, 200);
		fenster.add(area);

		b = new JButton("test");
		b.setBounds(100, 100, 100, 50);
		b.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				
				startThread();
			}
		});
		fenster.getContentPane().add(area);
		fenster.getContentPane().add(b);
		fenster.setVisible(true);

	}
	
	public void startThread() {
		Thread t = new Thread(new Updater());
		t.start();
	}



	public static void main(String[] args) {
		new Oberflaeche();
	}

	class Updater implements Runnable{

		@Override
		public void run() {
			try {
				for(int i=0; i<5; i++){
					area.append(i+"\n");
					Thread.sleep(1000);
				}
			}
			catch (InterruptedException e) {}
		}
				
		
	}
}
Dieses Beispile hat eine innere Klasse, die die textarea updated.
 
Zuletzt bearbeitet:

Babu

Mitglied
Danke für die Lösung.
Ich würde gerne auch noch verstehen, warum deine Variante funktioniert und meine nicht.
Gibts dafür eine logische Erklärung? (wohl eher eine rethorische Frage)

EDIT:
Liegts vielleicht daran, dass ich den Haupthread nicht einfriereden darf mit Thread.sleep()? Das würde erklären, warum deine Variante funktioniert.
Dann stellt sich mir die Frage, ob das in der Praxis so üblich ist. Also für jedes Objekt eine eigene Klasse mit entsprechender run() Methode. Erscheint mir doch sehr aufwändig :eek:
 
Zuletzt bearbeitet:

knilch

Bekanntes Mitglied
ok,erst mal:
In einen Konstruktor ist es nicht gut, einen Thread zu initalisieren und dann dort direkt zu starten. Das gehört in eine separate methode.

Dann:
Dein Aufbau vom JFrame ist nicht korrekt.
In Zeile 17 machst du: fenster.setVisible(true); --> .setVisible gehört ans Ende, wenn alle Elemente im Frame appended sind.
JFrame hat ein Container. In diesen Container gehören alle Elemente --> fenster.getContentPane().add(button)
So wie du es machst, ist nicht so ideal... fenster.add(b);

Dann:
Deine Klasse Oberflaeche erweitert ein JFrame. das Interface Runnable muss nicht von der Oberflaeche implementiert werden. Da ein JFrame und somit auch Oberflaeche nicht in einen separaten Thread gehört. Das wäre einfach too much.
Somit wird die Methode @override public void run() {} überflüssig.

Nun warum die Implementation von mir den update macht:
Wenn auf "test" gedrückt wird, so wird ein von Oberflaeche unabhängiger Thread erstellt (Thread t = new Thread(new Updater()); ) und dann mit t.start(); gestartet. Die run- Methode von Updater macht nun appendet nun jede Sekunde die TeaxArea vom Gui.

In deiner Variante startest du zwar auch einen Thread mit Thread t = new Thread(this);
t.start();
aber dieser wird im Konstruktor gestartet. Dieser macht aber nur einen repaint... thats it.

Sobald bei deiner implementation auf den Button start gedrückt wird, wird draw ausgeführt. Diese macht 5 mal ein area.append(i+"\n"), wartet dann 1000ms und ist fertig. Da die Methode draw erst nach 1000 ms fertig ist, wird die textArea erst updated, wenn draw beendet ist. (da das Gui, erst wieder die Kontrolle übernehmen kann und updated kann, wenn draw fertig ist)
Ich hoffe dies zeigt dir wieso die Variante von dir nicht das von dir gewünschte Ergebnis zeigt.
Dann stellt sich mir die Frage, ob das in der Praxis so üblich ist. Also für jedes Objekt eine eigene Klasse mit entsprechender run() Methode. Erscheint mir doch sehr aufwändig :eek:
Jedes Objekt in eine Klasse, dass kommt darauf an, was genau das Objekt ist, und was für Methoden für das Objekt implementiert werden.
Nicht für jede Klasse muss Runnable implementiert werden, das kommt auch wieder auf den Context drauf an.
 
Zuletzt bearbeitet:

Ähnliche Java Themen

Neue Themen


Oben