Problem Thread.sleep() und JProgressBar

Patrick_85

Mitglied
Hallo alle zusammen haben ein kleines Problem mit einer jProgressBar, in der ich nach Betätigung eines Buttons alle 1 sec. den Wert erhöhen möchte. Jedoch sobald ich auf den Button drücke, passiert erst nach 20 sec. was sichtbares, nachdem die for-Schleife durchlaufen wurde. Ich möchte jedoch, dass nach jedem Schleifendurchlauf was Sichtbares auf der jProgressBar passiert! hatte es auch schon mit repaint() Veruscht!

Habe drei Klassen, die folgendermaßen aussehen:

Main.class
Code:
package src;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Window win = new Window();

	}

}

Window.class
Code:
package src;

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

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JProgressBar;

public class Window extends JFrame {
	
	private JProgressBar prog;
	private JButton button;
	private Function function;
	
	public Window(){
		setLayout(null);
		function = new Function(this);
		setBounds(50, 50, 300, 300);
		prog = new JProgressBar();
		add(prog).setBounds(20, 20, 50, 20);
		button = new JButton("Start");
		button.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				try {
					function.run();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
		});
		add(button).setBounds(100, 20, 50, 20);
		setVisible(true);
	}
	
	public JProgressBar getProgressBar(){
		return prog;
	}

}

Function.class
Code:
package src;

public class Function {
	
	private Window window;
	
	public Function(Window window){
		this.window = window;
	}
	
	public void run() throws InterruptedException{
		for(int i=0;i<20;i++){
			window.getProgressBar().setValue(i);
			window.getProgressBar().repaint();
			Thread.sleep(1000);
		}
	}

}


Würde mich sehr freuen wenn ihr mir vielleicht helfen könntet oder hilfreiche Tipps geben könntet!
Gruß
Patrick
 
Code:
function.run();
muss in nem separaten Thread laufen. Die Aufrufe auf die Progressbar solltest du dann mit den SwingUtilities auf den EDT legen.
 
Noch ein paar Tipps:

- es gibt eine Klasse im JDK namens java.awt.Window, somit ist deine Namenswahl dort nicht glücklich. Benutze nach Möglichkeit immer eindeutige und eigene Namen.

-da du ja eh schon die run() methode "überschreibst", könntest du Function auch von Thread erben lassen. also
Java:
Function extends Thread

dann startest du die run() mit
Java:
function.start();

-und gaaaaaaaaanz wichtig: Java™ Quelltext ist bitte in
Java:
-Tags zu schreiben!!!![/B][/SIZE][/COLOR] ... wobei das "bitte" mal da raus müsste.

Gruß Vanny
 
Zuletzt bearbeitet von einem Moderator:
Und noch mal zu dem, was EikeB geschrieben hat:
Java:
SwingUtilities.invokeLater(Runnable run);
Damit führst du das was in der Runnable geschehen soll, auf dem Event Dispatch Thread (EDT) aus.

EikeBs Vorschlag ist, dass du die Zeilen
Java:
window.getProgressBar().setValue(i);
			window.getProgressBar().repaint();
in einer Runnable ausführst 🙂
 
Hallo alle zusammen, ich hatte es folgendermaßen versucht, jedoch klappt es noch nicht so ganz! Ich hoffe ihr könnte mir hilfreiche Tipps geben!
Hatte es folgendermaßen geändert:

Window.class: (Habe den Klassenname jedoch noch nicht geändert 😉, wollte erst die richtige Funktionalität haben!)

Java:
package src;

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

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

public class Window extends JFrame {
	
	private JProgressBar prog;
	private JButton button;
	private Function function;
	private Window window;
	private int x = 0;
	
	public Window(){
		window = this;
		setLayout(null);
		function = new Function(this);
		setBounds(50, 50, 300, 300);
		prog = new JProgressBar();
		add(prog).setBounds(20, 20, 50, 20);
		button = new JButton("Start");
		button.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {

				for(int i=0;i<15;i++){
					SwingUtilities.invokeLater(new Runnable() {
						@Override
						public void run() {
							window.getProgressBar().setValue(x);
							window.getProgressBar().repaint();
							x++;							
						}
					});
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					//SwingUtilities.invokeLater(function);
					//t1.start();
				}
			}
		});
		add(button).setBounds(100, 20, 50, 20);
		setVisible(true);
	}
	
	public JProgressBar getProgressBar(){
		return prog;
	}

}

Meine Function Klasse sieht jetzt folgendermaßen aus:

Java:
package src;


public class Function implements Runnable{
	
	private Window window;
	private int i =0;
	
	public Function(Window window){
		this.window = window;
	}
	public Function(){
		
	}
	
	public void run(){
			window.getProgressBar().setValue(i);
			window.getProgressBar().repaint();
			i++;
	}

}
 
Hallo alle zusammen, ich hatte es folgendermaßen versucht, jedoch klappt es noch nicht so ganz! Ich hoffe ihr könnte mir hilfreiche Tipps geben!

Hallo Patrick,
wenn ich das mal so offen sagen darf, du benötigst nicht ein paar hilfreiche Tipps, wie du sagst, sondern dir fehlen die totalen Basics der Thread-Programmierung. Was du da programmierst wird nie und nimmer funktionieren. Ich hoffe du verstehst das nicht falsch.

Nun jedoch zu deinem Problem:
Hier mal ein Vorschlag wie man es machen könnte.

1) Verwerfe den ganzen Code und fang neu an.
2) Schreibe eine Klasse, die allein nur die GUI repräsentiert, also von JFrame erbt.
3) Implementiere in dieser Klasse die beiden Controls vom Typ "JButton" und "JProgressBar" und setze die Eigenschaftswerte (insb. auch mit setMaximum den Maxvalue der JProgressBar)
4) Entwerfe eine (anonyme) innere Klasse, die für den JButton den Actionlistener realisiert.
5) Instanziere und registriere den Listener beim JButton in der Konstruktormethode der GUI-Klasse.

6) Schreibe eine eigene Klasse, welche für die JProgressbar die Funktionalität beinhaltet.
7) Dazu sollte diese Klasse (wie zuvor schon mal gepostet) von der Klasse Thread erben und als Dämon implementiert werden. (Das Interface "runnable" wurde in JAVA implementiert, weil JAVA keine Mehrfachvererbung kennt. Hier kannst du besser ganz einfach die Klasse Thread erweitern) Schreibe einen Konstruktor, der als Parameter eine Referenz auf eine JProgessbar übergeben bekommt.
8) Schreibe die run-Methode dieser Klasse und dort eine Schleife, die den Wert der (per Konstruktor übergebenen) JProgressBar setzt und in jedem Schleifendurchlauf mit sleep(1000) eine Sekunde lang den Thread schlafen legt.

9) In der methode ActionPerformed der Klasse des Actionlisteners für den JButton instanzierst du nun ein Objekt der oben zuvor programmierten Thread-Klasse und übergibst eine Referenz auf deine JProgressBar. Den Thread startest du anschließend mit [Objektbezeichner].start().

(Hier solltest du später in einem weiteren Schritt verhindern, dass der Thread mehrfach gestartet werden kann, solange eine Instanz des Thread noch lebt.)

Das sollte dir weiterhelfen.

Gruß
JP
 
Zuletzt bearbeitet:
Hallo JavaProfi, Dankeschön für deine sehr hilfreiche Vorgehensweise und Erläuterung! Habe es endlich ans Laufen bekommen und auch mehr Verständnis in Sachen Thread-Programmierung bekommen!
Danke !!
 

Neue Themen


Zurück
Oben