JLabel & invokeLater

Javazubi

Grünschnabel
Hi,

ich habe viele ähnliche Postings gelesen, aber irgendwie komme ich nicht zur Lösung meines Problems. Ich habe ein JLabel, dem ich zur Laufzeit einen neuen Text zuweisen möchte. Mein Hauptthread (Frame) wird wie folgt gestartet:

Code:
public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ATC_Frame().setVisible(true);
            }
        });
    }

Auf der Form befindet sich eine JTable, deren Click-Event abgefangen wird und folgenden Code aufruft:

Code:
1  private void tueWas() {
	
2  	String[] conn_status = new String[2];
3  	conn_status[0] = "Verbindung wird aufgebaut";

5	System.err.println(conn_status[0]);
6	//setText des Labels soll ausgeführt werden
7	SwingUtilities.invokeLater( new AddEvent(lblMeldung, conn_status[0]) );

8	thread1 = new thread1_klasse(x, x, x, x, x);
9	thread1.start();

10	//Ich übergebe das String-Array, damit ich ein Call-By-Reference habe
11	//und der Zweite Thread das hier lokale conn_status[0] änder kann
12	thread1.starteThread2(x, x, x, conn_status);

13	//Hier wird die Änderung von conn_status[0] durch Thread2 abgewartet
14	while (conn_status[0].equals("Verbindung wird aufgebaut")) {
15	   try
16	   {
17	         Thread.sleep(1000);
18	         System.out.println("Warte");
19	   }
20	   catch(Exception e)
21	   {
22	         e.ToString();
23	   }
24	}

25	//Nach der Änderung von conn_status[0] durch Thread2 soll der neue Text
26	//Verbindung "steht" oder "steht nicht" angezeigt werden
27	System.err.println(conn_status[0]);
28	SwingUtilities.invokeLater( new AddEvent(lblMeldung, conn_status[0]) );

29  }


30  class AddEvent implements Runnable {

31	private JLabel lbl;
32	private String text;
	
33	public AddEvent(JLabel lbl, String text) {
34		this.lbl = lbl;
35		text = text;
36	} 
	
37	public void run() {
38             System.out.println("IN ADDEVENT");
		lbl.setText( text );
39	} 

40  }

Nun erfolgt aber weder in Zeile 7 noch in Zeile 28 die gewünschte Änderung des Labels. Nachdem der 2. Thread den Text geändert hat, sehe ich den Erfolg über das System.err.println in Zeile 27 und erst ganz zum Schluß die beiden Ausgaben von "IN ADDEVENT" in Zeile 38.

Kann mir jemand helfen?

Gruß
 
Warum implementiert deine Klasse AddEvent denn das Interface Runnable? Erscheint mir irgendwie überflüssig, warum, setzt du den Text des Labels nicht einfach so?
 
Hi,

weil es so einfach nicht funktioniert. Ein label.setText("irgendwas") klappt aus dem Main-Thread nicht. Das habe ich beim Lesen der Foren schon herausgefunden. Darum ja auch das invokeLater.

Die Klasse addEvent ist eine von 4 bis 5 Varianten, die ich bisher gefunden habe, um die GUI zur Laufzeit zu aktualisieren. Alle Varianten haben in meinem Code den selben Effekt. Die Ausgabe von Zeile 38 wird als allerletztes angezeigt und daher nicht parallel zum Main-Thread abgearbeitet. Selbst wenn der Verbindungsaufbau in Zeile 12 in einen Timeout läuft (hier wäre ja in jedem Fall genügend Zeit das Label zu aktualisieren), wird addEvent->run() danach durchlaufen UND WIE SCHÖN - selbst dann ändert sich der Text des Labels nicht! :suspekt:
 
Sorry vielleicht verstehe ich dein Problem nicht so ganz aber folgender Code funktioniert einwandfrei bei mir..
Java:
package test;

import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JLabel;

public class labelTest extends JFrame {

	private static final long serialVersionUID = 1L;

	private JPanel jContentPane = null;

	private JScrollPane jScrollPane = null;

	private JTable jTable = null;

	private JLabel jLabel = null;

	/**
	 * This method initializes jScrollPane	
	 * 	
	 * @return javax.swing.JScrollPane	
	 */
	private JScrollPane getJScrollPane() {
		if (jScrollPane == null) {
			jScrollPane = new JScrollPane();
			jScrollPane.setViewportView(getJTable());
		}
		return jScrollPane;
	}

	/**
	 * This method initializes jTable	
	 * 	
	 * @return javax.swing.JTable	
	 */
	private JTable getJTable() {
		if (jTable == null) {
			jTable = new JTable(5,5);
			jTable.addMouseListener(new java.awt.event.MouseAdapter() {
				public void mouseClicked(java.awt.event.MouseEvent e) {
					try {
						Thread.sleep(5000);
					} catch (InterruptedException ie) {
						System.out.println(ie.getMessage());
					}
					jLabel.setText("verbunden");
				}
			});
		}
		return jTable;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				labelTest thisClass = new labelTest();
				thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				thisClass.setVisible(true);
			}
		});
	}

	/**
	 * This is the default constructor
	 */
	public labelTest() {
		super();
		initialize();
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(300, 200);
		this.setContentPane(getJContentPane());
		this.setTitle("JFrame");
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jLabel = new JLabel();
			jLabel.setText("nicht verbunden");
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getJScrollPane(), BorderLayout.CENTER);
			jContentPane.add(jLabel, BorderLayout.NORTH);
		}
		return jContentPane;
	}

}
 
Hi,

das Problem mit der NICHT nebenläufigen Ausführung von AddEvent hat sich erledigt. Ich habe im Konstruktor "new Thread( this ).start();" hinzugefügt. Ebenfalls habe ich den Parameter "text" des Konstruktors an this.text übergeben :) Die Klasse sind nun so aus.

Code:
class AddEvent implements Runnable {
	private JLabel lbl;
	private String text;
	
	public AddEvent(JLabel lbl, String text) {
                System.out.println("IN Konstruktor conn_status[0] = " + text);
		this.lbl = lbl;
		this.text = text;
                new Thread( this ).start();
	} 
	
	public void run() {
                System.out.println("IN ADDEVENT " + this.text);
                lbl.setText( this.text );
	} 
}

Aber ein Problem bleibt! Das NACHTRÄGLICHE ändern des Textes mit lbl.setText(this.text) funktioniert nicht bzw. die Änderung wird nicht angezeigt.

Du hast schon recht, wenn man das Label mit
jLabel = new JLabel();
erstellt und direkt danach ein
jLabel.setText("nicht verbunden");
aufruft wird der Text gesetzt. Aber setze bitte mal einen Button auf deine Form und füge einen ActionListener hinzu, der den ButtonClick abfängt und probiere ein erneutes jLabel.setText("...") in diesem Listener. Es wird dir nicht gelingen!

Hiiiilfeeeeeeeee! :)
 
Also ich glaube langsam das wir irgendwie ziemlich an einander vorbei Reden :/
meinst du sowas
Java:
package test;

import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JLabel;
import javax.swing.JButton;

public class labelTest extends JFrame {

	private static final long serialVersionUID = 1L;

	private JPanel jContentPane = null;

	private JScrollPane jScrollPane = null;

	private JTable jTable = null;

	private JLabel jLabel = null;

	private JButton jButton = null;

	/**
	 * This method initializes jScrollPane	
	 * 	
	 * @return javax.swing.JScrollPane	
	 */
	private JScrollPane getJScrollPane() {
		if (jScrollPane == null) {
			jScrollPane = new JScrollPane();
			jScrollPane.setViewportView(getJTable());
		}
		return jScrollPane;
	}

	/**
	 * This method initializes jTable	
	 * 	
	 * @return javax.swing.JTable	
	 */
	private JTable getJTable() {
		if (jTable == null) {
			jTable = new JTable(5,5);
			jTable.addMouseListener(new java.awt.event.MouseAdapter() {
				public void mouseClicked(java.awt.event.MouseEvent e) {
					try {
						Thread.sleep(5000);
					} catch (InterruptedException ie) {
						System.out.println(ie.getMessage());
					}
					jLabel.setText("verbunden");
				}
			});
		}
		return jTable;
	}

	/**
	 * This method initializes jButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJButton() {
		if (jButton == null) {
			jButton = new JButton();
			jButton.setText("Knopf");
			jButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					jLabel.setText("geht doch");
				}
			});
		}
		return jButton;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				labelTest thisClass = new labelTest();
				thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				thisClass.setVisible(true);
			}
		});
	}

	/**
	 * This is the default constructor
	 */
	public labelTest() {
		super();
		initialize();
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(300, 200);
		this.setContentPane(getJContentPane());
		this.setTitle("JFrame");
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jLabel = new JLabel();
			jLabel.setText("nicht verbunden");
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getJScrollPane(), BorderLayout.CENTER);
			jContentPane.add(jLabel, BorderLayout.NORTH);
			jContentPane.add(getJButton(), BorderLayout.SOUTH);
		}
		return jContentPane;
	}

}
funktioniert bei mir super...
 
Sorry, dass ich bei deinem vorletzten posting deinen Listener jTable.mouseClicked() übersehen habe. Genau sowas meinte ich. Und das funktioniert bei dir Bei mir leider nicht... grmbl
 
Die Klasse hat mittlerweile mehr als 1000 Zeilen Code. Ich muss mich daher auf das Wesentliche beschränken.

Code:
public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ATC_Frame().setVisible(true);
            }
        });
}

Der Konstruktor der Klasse ATC_Frame ruft die Funktion fuelle_tabelle() auf.
Die Funktion fuelle_tabelle() fügt einem JPanel eine JTable hinzu.

Code:
private void fuelle_tabelle() {
	
	lblFehler = new JLabel();
	table = new JTable(daten, ueberschriften);
.
.
.

	//Listener für Tabelle hinzufuegen
	table.addMouseListener(new java.awt.event.MouseAdapter() {
	            public void mouseClicked(java.awt.event.MouseEvent evt) {
	                handler_table_click(evt);
	            }
	});

}

Bei einem Click auf die Tabelle wird der Code in handler_table_click() definitiv ausgeführt.

Code:
private void handler_table_click(java.awt.event.MouseEvent evt) {
        
	lblFehler.setText("Test");

.
.
.

}

Aber das Label ändert seinen Text nicht. Danke für deine Geduld...
 
Zurück