Swing update eines Labels nicht sichtbar

diggaa1984

Top Contributor
heyho,

das allseits beliebte Thema: "Komponente xy wird nicht geupdatet" 🙂

Mich hats nur auch grad wieder erwischt und ich find die Lösung net.
Java:
@Override
public void propertyChange(final PropertyChangeEvent evt) {
	if ("id".equals(evt.getPropertyName())) {
		//TODO: hier klappt was net, aber Event kommt durch und text intern korrekt
		idLabel.setText(idLabel.getText() + evt.getNewValue());
	}//if			
}//propertyChanged

das ist Teil eines JPanels, auf welchem ich ein Label für eine ID habe. Das Event wird ordnungsgemäß erkannt und auch bearbeitet. Beim debuggen sehe ich den Text des Label geändert. Allerdings nicht auf dem Panel ???:L

Erstellt wird die Gui wie folgt, ausgehend von einer anderen Klasse:
Java:
private void setupMainFrame() {
	SwingUtilities.invokeLater(new Runnable() {
	
		@Override
		public void run() {
			try {
				UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
			} catch (Exception e) {
				e.printStackTrace();
			}//try
				
			MainFrame mf = new MainFrame(GuiController.this);
			mf.setVisible(true);
		}//run
	});
}//setupMainFrame

Das Erzeugen des MainFrames, zieht alles erdenklich andere an Gui-Komponenten mit sich, somit werden doch alle auf dem EDT erstellt?!
Nur warum bekomm ich dann das setText() - Event nicht mit?
 
Kann man jetzt wohl so kaum etwas zu sagen bin ich der Meinung.
Hält
Code:
idLabel
auch wirklich eine Referenz auf das Label welches sich auf dem Panel befindet?
Ansonsten bereite doch mal einen kurzen Beispielcode vor den mal nachvollziehen und evtl. auch selbst ausführen kann
 
die letzten beiden genannten Befehle sind unnötig

is mir bewusst, daher hab ich die gar nich erst erwähnt 🙂

aehm mal ne Klasse die zu 99% die Struktur aufweist, welche bei mir intern vorliegt.
Die Änderung geschieht im MainController. Diese Änderung wird per PropertyChangeSupport an die Listener propagiert. Der GuiController erhält diese Events und leitet sie an die ihm bekannten Listener weiter, welche bei Bedarf das Event verarbeiten. Soviel zum groben Ablauf.

Java:
import java.beans.*;
import javax.swing.*;
import java.awt.*;
import java.util.*;


public class MainController {
	
	public static void main(String[] args) {
		MainController mc = new MainController();
		GuiController gc = new GuiController(mc);
		
		mc.setId(3);
	}//main
	
	
	/**************************  MAINCONTROLLER  ****************************/
	
	private int id = 0;
	private PropertyChangeSupport pcs;
	
	public MainController() {
		pcs = new PropertyChangeSupport(this);
	}//constructor
	
	public void setId(int id) {
		pcs.firePropertyChange("id",this.id, id);
		this.id = id;
	}//setId
	

	public void addPropertyChangeListener(PropertyChangeListener pcl) {
		pcs.addPropertyChangeListener(pcl);
	}//addPropertyChangeListener
	
	
	/**************************  GUICONTROLLER *******************************/
	
	public static class GuiController implements PropertyChangeListener {

		private MainController mainController;
		private java.util.List<PropertyChangeListener> listener;
	
	
		public GuiController(MainController mainController) {
			listener = new ArrayList<PropertyChangeListener>();
			this.mainController = mainController;
			this.mainController.addPropertyChangeListener(this);
			setupMainFrame();
		}//constructor


		public void addPropertyChangeListener(PropertyChangeListener pcl) {
			listener.add(pcl);
			System.out.println("GuiController - listener added: " + pcl.getClass().getName());
		}//addPropertyChangeListener
		
	
		@Override
		public void propertyChange(PropertyChangeEvent evt) {
			System.out.println("GuiController - incoming event: " + evt.getPropertyName());
			for (PropertyChangeListener pcl: listener) {
				System.out.println("Send event to: " + pcl.getClass().getName());
				pcl.propertyChange(evt);
			}//for
		}//propertyChangeListener
	
	
		/**
		* 
		*/
		private void setupMainFrame() {
			SwingUtilities.invokeLater(new Runnable() {
			
				@Override
				public void run() {
					try {
						UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
					} catch (Exception e) {
						e.printStackTrace();
					}//try
				
					MainFrame mf = new MainFrame(GuiController.this);
					mf.setVisible(true);
				}//run
			});
		}//setupMainFrame
	}//GuiController
	
	
	/**************************  MAINFRAME *******************************/
	
	private static class MainFrame extends JFrame {
		
		private static final String DEFAULT_TITLE = "Client-Application";
		private GuiController guiController;
	
	
		public MainFrame(GuiController guiController) {
			super(DEFAULT_TITLE);
			this.guiController = guiController;
			setup();
		}//constructor
	
	
		private void setup() {
			this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			this.setMinimumSize(new Dimension(1000,500));
		
			add(new MainPanel(guiController));
		
			this.setLocationRelativeTo(null);
			pack();
		}//setup

	}//MainFrame
	
	
	/**************************  MAINPANEL  ******************************/
	
	private static class MainPanel extends JPanel implements PropertyChangeListener {
		
		private JLabel idLabel;
		private GuiController guiController;
		
		public MainPanel(GuiController guiController) {
			super();
			this.guiController = guiController;
			this.guiController.addPropertyChangeListener(this);
			setup();
		}//constructor
		
		
		private void setup() {
			idLabel = new JLabel("ID: ");
			idLabel.setFont(new Font(idLabel.getFont().getFontName(), Font.BOLD, 14));
			add(idLabel);
		}//setup
		
		
		@Override
		public void propertyChange(final PropertyChangeEvent evt) {
			System.out.println(evt.getPropertyName());
			if ("id".equals(evt.getPropertyName())) {
				System.out.println("new Value: " + evt.getNewValue());
				//TODO: hier klappt was net, aber Event kommt durch und text intern korrekt
				idLabel.setText(idLabel.getText() + evt.getNewValue());
				System.out.println("new Label-Text: " + idLabel.getText());
			}//if			
		}//propertyChanged
	}//MainPanel
}

Das ganze als KSKB verpackt. Auffällig ist, das keine Ausgabe "send event to listener .. " aus dem GuiController erscheint. Der Listener "MainPanel" ist aber bekannt, wie der Ausgabe zu entnehmen ist. Die Ausgaben beim MainPanel fehlen ebenfalls .. warum weiss ich nicht, aber wie gesagt, beim debuggen kommt das Event an, und intern ist der Text des Labels korrekt geändert worden, nur seh ich diese Änderung nicht. So ich werd bald zum Zug müssen, habt ihr also n bissel Zeit zum Forschen 🙂
 
Zuletzt bearbeitet:
Naja, anhand der Ausgabe siehst du doch schon das Problem! Das Event wird gefeuert, bevor der Listener hinzugefügt wurde:
Java:
		try {
			Thread.sleep(4000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		mc.setId(3);

und dann solltest du auch etwas sehen können...
Der Code ist aber grausam *g*
 
hm ok .. im eigentlichen programm geschieht das ändern der ID erst, nachdem ich nen Socket aufmache und mit dem Server connected bin. Kann es also auch da passieren, dass das Erstellen des Sockets schneller is als die GUI!? mal testen

Optimierungsvorschläge gern gesehen, aber aus Zeitgründen erst später realisierbar ^^
 

Neue Themen


Zurück
Oben