Schleife verlangsamen

gabelo

Mitglied
Guten Tag,
ich hab ein kleines Programm erstellt, welches beim Betätigen eines Knopfes einen Zählerstand um 1 inkrementiert. Für die GUI habe ich Java Swing verwendet. Nun wollte ich, dass beim Betätigen des Knopfes der Zählerstand - langsam - hochzählt. Dafür hab ich eine For-Schleife implementiert und die Sleep Methode aufgerufen.

Das Problem ist, dass das Label sich nicht aktualisiert. Er zählt bis zur gewünschten Zahl und wartet pro Schleifendurchgang die angegebene Zeit. Nur das Label wird nicht aktualisiert. Was mach ich falsch?

Freundliche Grüße
P.S.: Jegliche weitere Kritik, die beim Überfliegen des Codes euch in den Kopf schießt, könnt ihr mir gerne mitteilen.

Der Code;
[CODE lang="java" title="Zaehler" highlight=""69-81""]package actionListenerJT;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

// Es wird eine Klasse Zaehler erstellt, die eine Sub-Klasse von JFrame
// ist und das ActionListener Interface implementiert
public class Zaehler extends JFrame implements ActionListener {

// Attribute
private JButton knopfZumBeenden;
private JButton zaehlerKnopf;
private JLabel label;
private JPanel panel;
private int gezaehlteZahl = 0;

// Konstruktur
public Zaehler (){
// Das erstellte Objekt ist mit der Super-Klasse JFrame automatisch
//ein Frame und soll einen Namen bekommen
// Die Groesse des Fensters soll festgelegt werden
this.setTitle("ActionListener Beispiel");
this.setSize(400, 100);

// Panel wird erzeugt für die Knoepfe
panel = new JPanel();

// JLabel-Objekt wird erzeugt und beschriftet
label = new JLabel();
label.setText("Zaehlerstand: " + String.valueOf(gezaehlteZahl));

//Knoepfe werden erzeugt und beschriftet
knopfZumBeenden = new JButton ("Beenden");
zaehlerKnopf = new JButton("Drueck mich fuer +1");

//Knoepfe werden dem ActionListener zugeordnet
zaehlerKnopf.addActionListener(this);
//benoetigt als Eingabeparameter ein Objekt mit dem Interface ActionListener
knopfZumBeenden.addActionListener(this);
//benoetigt als Eingabeparameter ein Objekt mit dem Interface ActionListener

//Knoepfe werden dem JPanel hinzugefügt
panel.add(knopfZumBeenden);
panel.add(zaehlerKnopf);

// Label wird dem Panel hinzugefügt
panel.add(label);

// Panel wird dem Objekt (das als Sub-Klasse vom JFrame
//automatisch ein Frame ist) hinzugefügt
this.add(panel);
this.setVisible(true);
}

// Methode

// Mit dem ActionListener Interface muss die Methode actionPerformed
//implementiert werden!

// Wird einer der Knoepfe gedrueckt, wird ein ActionEvent-Objekt erstellt:
// knopfBetaetigung
// Die Referenz auf das Objekt wird als Parameter uebergeben
public void actionPerformed (ActionEvent knopfBetaetigung){


// Ist das erstellte Objekt knopfBetaetigung der zaehlerKnopf,
//soll die gezaehlte Zahl um 1 erhoeht werden
//Dann soll der Label-Text die gezaehlte Zahl ausgeben
if (knopfBetaetigung.getSource() == this.zaehlerKnopf) {

for (int i = 1; i <= 3; i++ ){
gezaehlteZahl = i;
label.setText("Zaehlerstand: " + String.valueOf(gezaehlteZahl));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
// Ist das erstellte Objekt knopfBetaetigung der knopfZumBeenden,
// soll das Fenster geschlossen werden
else if (knopfBetaetigung.getSource() == this.knopfZumBeenden) {
System.exit(0);
}
}
}[/CODE]
 

mihe7

Top Contributor
Das Problem ist, dass das Label sich nicht aktualisiert. Er zählt bis zur gewünschten Zahl und wartet pro Schleifendurchgang die angegebene Zeit. Nur das Label wird nicht aktualisiert. Was mach ich falsch?
Deine actionPerformed-Methode wird von Swing aufgerufen, die Methode läuft somit im UI-Thread, der auch für das Neuzeichnen/Aktualisieren von Fensterinhalten zuständig ist. Erst, wenn die actionPerformed-Methode verlassen wird, kann auch das Fenster neu gezeichnet werden.

Wenn Du einen automatischen Zähler haben willst, musst Du einen separaten Thread verwenden. Am ehesten dürftest Du mit einem javax.swing.Timer zurechtkommen.
 

Blender3D

Top Contributor
Jegliche weitere Kritik, die beim Überfliegen des Codes euch in den Kopf schießt, könnt ihr mir gerne mitteilen
Ich würde:
1) nicht von JFrame erben. Besser einen JPanel erweitern und in JFrame einsetzen.
2) Den Counter in eine eigene Klasse auslagern z.B ein JLabel erweitern.
3) Jedem Button seinen eigenen Listener geben.
Im folgenden Beispiel lassen sich ganz einfach durch die Auslagerung des Counters, zwei verschiedene Countdowns starten.
Der JFrame nimmt den CounterPanel , der das eigentliche Programm realisiert, auf.
[CODE lang="java" title="StartCounter" highlight="7"]import javax.swing.JFrame;

public class StartCounter {
public static void main(String[] args) {
JFrame frame = new JFrame("ActionListener Beispiel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new CounterPanel(500, 60));
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
}
}[/CODE]
[CODE lang="java" title="CounterPanel" highlight="20-34"]import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class CounterPanel extends JPanel {
private CountDownLabel countDownLabelA = new CountDownLabel("Zähler A");
private CountDownLabel countDownLabelB = new CountDownLabel("Zähler B");

public CounterPanel(int width, int height) {
setPreferredSize(new Dimension(width, height));
JButton exit = new JButton("Ende");
JButton startCountDownA = new JButton("Start A");
JButton startCountDownB = new JButton("Start B");
add(exit);
add(startCountDownA);
add(countDownLabelA);
add(startCountDownB);
add(countDownLabelB);
exit.addActionListener(e -> {
System.exit(0);
});
startCountDownA.addActionListener(e -> {
startCownDown(countDownLabelA, 10);
});
startCountDownB.addActionListener(e -> {
startCownDown(countDownLabelB, 5);
});
countDownLabelA.setCountDownListener(e -> {
printCountDownOverMsg(e.getLabel());
});
countDownLabelB.setCountDownListener(e -> {
printCountDownOverMsg(e.getLabel());
});

}

private static void printCountDownOverMsg(String msg) {
System.out.println("Countdown is over " + msg);
}

private static void startCownDown(CountDownLabel countDown, int duration) {
if (countDown.isRunning())
return;
countDown.start(duration);
}
}[/CODE]
[CODE lang="java" title="CountDownLabel" highlight="33-47"]import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.border.BevelBorder;

@SuppressWarnings("serial")
public class CountDownLabel extends JLabel implements Runnable {
private int value;
private boolean running = false;
private Thread animator = null;
private String label;
private CountDownListener listener;

public CountDownLabel(String label) {
super(" "+ label+ " ");
this.label = label;
setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
}

public String getLabel() {
return label;
}

public int getValue() {
return value;
}

public boolean isRunning() {
return running;
}

@Override
public void run() {
while (running) {
setText(" " + label + " " + value + " ");
if (value <= 0) {
running = false;
if (listener != null)
listener.countDownOver(this);
} else
value--;
repaint();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public void setCountDownListener(CountDownListener listener) {
this.listener = listener;
}

public boolean start(int value) {
if (isRunning())
return false;
this.value = value;
running = true;
animator = new Thread(this);
animator.start();
return true;
}

public void stop() {
running = false;
animator = null;
}

}[/CODE]
[CODE lang="java" title="CountDownListener"]public interface CountDownListener {
public void countDownOver(CountDownLabel e);
}[/CODE]
 

Neumi5694

Top Contributor
1) unterschreib ich sofort
2) Noch eine Idee: Reines Interface, das die Komponente per getDisplayComponent() liefert, damit man sich nicht auf ein JLabel einschießt.
3) Reine Geschmackssache. Mit einem Switch über das ActionCommand hat man vor Lambda gearbeitet, als noch viel mehr Code anfiel.
Wenn nur ein Befehl ausgeführt wird, liest sich eine Schreibweise ohne geschweifte Klammern meiner Meinung nach übrigens deutlich angenehmer.
Java:
        startCountDownA.addActionListener(e -> startCownDown(countDownLabelA, 10));
        startCountDownB.addActionListener(e -> startCownDown(countDownLabelB, 5));
        countDownLabelA.setCountDownListener(e -> printCountDownOverMsg(e.getLabel()));
        countDownLabelB.setCountDownListener(e -> printCountDownOverMsg(e.getLabel()));
Falls printCountDownOverMsg den Event akzeptiert und sich dort das Label selbst rausholt, kann man's auch als Listener direkt ansprechen.
Java:
        countDownLabelA.setCountDownListener(this::printCountDownOverMsg);
        countDownLabelB.setCountDownListener(this::printCountDownOverMsg);
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Vokabelprogram - Schleife für Liste soll schrittweise durchlaufen werden AWT, Swing, JavaFX & SWT 3
ms_cikar Update swingUtilities Repaint in der Schleife AWT, Swing, JavaFX & SWT 3
W fillRect() in Schleife spukt nur Fehler aus AWT, Swing, JavaFX & SWT 3
heinz ketchup While-Schleife in einem Service für GUI AWT, Swing, JavaFX & SWT 22
A Swing JLabels in einer ForEach Schleife an den JPanel anheften (UNO Netzwerkspiel) AWT, Swing, JavaFX & SWT 1
S While Schleife im Actionlistener AWT, Swing, JavaFX & SWT 1
R MVC Observer While-Schleife AWT, Swing, JavaFX & SWT 3
L JTabbedPane mit for Schleife aufbauen AWT, Swing, JavaFX & SWT 4
I Applet BlueJ Applet - Bild mit if-Schleife zeichnen lassen AWT, Swing, JavaFX & SWT 16
A Problem: repaint() - Schleife AWT, Swing, JavaFX & SWT 3
J GridBagLayout mit Hilfe einer For-Schleife befüllen AWT, Swing, JavaFX & SWT 1
C In der Schleife ActionListener aktivieren AWT, Swing, JavaFX & SWT 3
C SWT Tab in Schleife AWT, Swing, JavaFX & SWT 9
C Schleife auf Mausklick warten lassen AWT, Swing, JavaFX & SWT 6
S Farbverlauf in for-Schleife berechnen AWT, Swing, JavaFX & SWT 4
H Swing Komponenten per Schleife auf JFrame AWT, Swing, JavaFX & SWT 4
F JLabel mittles Schleife einbinden?? AWT, Swing, JavaFX & SWT 3
D Swing JLabels in einer Schleife aktualisieren AWT, Swing, JavaFX & SWT 2
S Problem mit JLabel (Bewegung in Schleife) AWT, Swing, JavaFX & SWT 7
D Schleife für Button AWT, Swing, JavaFX & SWT 4
R for-Schleife in Applet ausgeben AWT, Swing, JavaFX & SWT 3
H Mit for-schleife die Componenten eines Frames verändern AWT, Swing, JavaFX & SWT 5
A Jedes JTextfield einer klasse in einer foreach schleife abarbeiten AWT, Swing, JavaFX & SWT 3
R jTextField in Schleife ausfuellen AWT, Swing, JavaFX & SWT 4
I Swing repaint wird in for-Schleife aufgerufen - was passiert? AWT, Swing, JavaFX & SWT 12
M Button funktioniert nicht mehr wenn Schleife läuft AWT, Swing, JavaFX & SWT 3
R zweidim. JButton-Array in Schleife -> NullPointerExceptio AWT, Swing, JavaFX & SWT 2
S JMenu und ActionListener per Schleife erzeugen AWT, Swing, JavaFX & SWT 3
R das letzte JLabel in der Schleife will nicht an seinen Platz AWT, Swing, JavaFX & SWT 2
J ActionListener nimmt keine for()-Schleife? AWT, Swing, JavaFX & SWT 4
G For-Schleife AWT, Swing, JavaFX & SWT 4
B Deklaration von vielen Buttons mit Schleife vereinfachen? AWT, Swing, JavaFX & SWT 9
P JRadioButton in Schleife erstellen > wo liegt mein Fehler AWT, Swing, JavaFX & SWT 2
M Schleife mit Button abbrechen AWT, Swing, JavaFX & SWT 4
T JPanel in Schleife anlegen AWT, Swing, JavaFX & SWT 7
raptorrs JTextfelder werden in while-Schleife nicht aktualisiert AWT, Swing, JavaFX & SWT 5
F Einlesen von text in textArea mittels for-schleife AWT, Swing, JavaFX & SWT 3
R Grafische Benutzereingabe in For-Schleife AWT, Swing, JavaFX & SWT 8
L vermutlich Problem in meiner for-Schleife AWT, Swing, JavaFX & SWT 6
S Mehrere Buttons in einer Schleife erzeugen . AWT, Swing, JavaFX & SWT 3
G Schleife mit repaint funktioniert nicht. AWT, Swing, JavaFX & SWT 7
A JTable Schleife AWT, Swing, JavaFX & SWT 4
G while schleife - keylistener AWT, Swing, JavaFX & SWT 4
M JDialog in for-Schleife mit Komponenten bestücken AWT, Swing, JavaFX & SWT 6
S JButton über Schleife erstellen AWT, Swing, JavaFX & SWT 4
F Frame wird nicht angezeigt nach while-Schleife AWT, Swing, JavaFX & SWT 3
R Button löst Schleife aus, danach friert die GUI ein ? AWT, Swing, JavaFX & SWT 7
S Swing Gui Aktionen verlangsamen AWT, Swing, JavaFX & SWT 8
M Applet repaint() verlangsamen AWT, Swing, JavaFX & SWT 7

Ähnliche Java Themen

Neue Themen


Oben