Ich will exemplarisch den Text eines JButtons 2 Mal nacheinander ändern (mit einer kleinen Pause dazwischen). Solange ich dies ausserhalb des ActionListeners mache, funktioniert es perfekt. Wenn ich den Code in den ActionListener / actionPerformed einbaue, zeigt er mir die erste Textänderung nicht mehr an (es sieht so aus, als würde er nur die Pause und die zweite Textänderung machen).
Ich habe das Gefühl es hängt entweder mit dem Repaint-Aufruf oder mit der Sichtbarkeit des Buttons innerhalb von actionPerformed zusammen. Aber ich komme nicht darauf.
Du blockierst mit dem ActionListener den Event Dispatch Thread. Veränderungen der UI müssen im Event Dispatch Thread stattfinden, das "Warten" muss in einem eigenen Thread stattfinden. Du musst innerhalb des ActionListener innerhalb eines Threads "warten" und innerhalb des Event Dispatch Thread die UI ändern:
Vielen Dank für deine Hilfe. Es funktioniert einwandfrei.
Die Syntax ist für mich noch etwas schwer nachzuvollziehen aber ich will zuerst sicherstellen, dass ich den Gesamtmechanismus verstanden habe.
Verstehe ich das also richtig, dass das Warten (Sleep) im Thread des ActionListeners (hier new Thread) läuft während die beiden invokelater-Blocks erlauben das Update der UI im Event Dispatch Thread auszuführen?
Verstehe ich das also richtig, dass das Warten (Sleep) im Thread des ActionListeners (hier new Thread) läuft während die beiden invokelater-Blocks erlauben das Update der UI im Event Dispatch Thread auszuführen?
Ja. Der EDT arbeitet eine Warteschlange (Event Queue) ab, in der zu verarbeitende Ereignisse oder auch Runnables liegen. Mit invokeLater wird ein Runnable in diese Warteschlange eingereiht.
Ja die Graphik hilft wirklich um es zu verstehen. Danke.
Für meinen konkreten Fall habe ich die Struktur mit den Invokelater in eine For Schleife eingebaut.
Wie kann ich den Zähler t in die Methode run() innerhalb des invokelaters übergeben?
[CODE lang="java" highlight="22;26"]public class Fenster extends JFrame {
private JPanel contentPane;
public Fenster() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
setContentPane(contentPane);
JButton meinButton = new JButton("New button");
contentPane.add(meinButton);
setVisible(true);
meinButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == meinButton) {
new Thread(new Runnable() {
@Override
public void run() {
for (int t=5;t>=0;t--) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
meinButton.setText("t=" + t);
meinButton.repaint();
}
});