Swing Datentransfer zwischen JPanels

buntuswalus

Mitglied
Ich habe ein Problem mit Swing und es ist hoffentlich ganz leicht 🙂

Ich habe ein JFrame welches 2 JPanels beinhaltet und ein Datenobjekt welches an beide übergeben wird. Ein JPanel besitzt Buttons und modifiziert mit diesen die Werte des Datenobjekts. Das andere JPanel gibt die Daten aus.

Das ist sozusagen die sehr vereinfachte version meines Programms 🙂

Nun habe ich ein Problem. Wenn ich Das Programm starte werden die Defaultwerte wie gewollt ausgegeben. Wenn ich jedoch die Werte verändere (mit den buttons im ersten JPanel), so wird die Ausgabe im zweiten nicht aktualisiert.

Hat jemand eine schlaue idee? :rtfm:
 
Zuletzt bearbeitet:
bei jeder Änderung in JPanel1 oder allgemein im Datenobjekt steht auch
jPanel2.aktualisiereDich();

falls sich die beiden nicht kennen, hilft das Observer/ Listener-Konzept
 
klingt gut, ist aber abhängig davon, was überhaupt zu tun ist,
wenn du in Textfeldern oder Labels neuen Text setzt, dann gehts auch ohne repaint()
 
Teils Teils. Das ausgabePanel hat 2 TextField's und ein weiteres Panel welches Datensätze ausgibt (So ein bisschen Excel ähnlich). Hm, das bedeutet, wenn ich nur die Werte der TextField's neu setze, dann aktualisieren sich zumindest die von selbst?
 
Das TextField bekommt eine Update sobald der Text gesetzt wird. Aber nur wenn ignoreRepaint(false) Wenn es immer noch nicht geht, poste mal ein bisschen Code!
 
Mhhhh, gefällt dem Programm noch nicht.
Also das repaint() macht irgendwie nichts.

mein Datenobjekt (QueryControl) hat unter anderem nun dies:
Java:
	/**
	 * Über diese Methode können sich Output JPanels registrieren. Registrierte Panels werden 
	 * automatisch zum Aktualisieren aufgefordert wenn sich die Werte der QueryControl verändern:
	 */
	public void alsOutputRegistrieren(JPanel panel) {
		outputPanels.add(panel);
	}
	/**
	 * Aktualisiert die Output Panels. Diese Methode wird von den Settern dieser Klasse automatisch ausgeführt
	 * (Also ergänzen wenn nötig!). Damit bleiben die Ausgabepanele stets aktuell zu den Benutzereingaben:
	 */
	private void aktualisiereOutputPanels() {
		Iterator<JPanel> it = outputPanels.iterator();
		while (it.hasNext()) {
			it.next().repaint();
		}
	}

Die Werte des Datenobjekts werden von einem anderen JPanel aus über Events verändert (JSpinner).
Alle Setter des Datenobjekts führen aktualisiereOutputPanels() aus.

Das AusgabePanel meldet sich wie folgt an:
Java:
public JPanel_Ergebnis(int width, int height, HashSet<Messwert> messwerte, QueryControl eingaben, Interpolator inpol) {
		// Eigenschaften definieren:
		super(new FlowLayout(FlowLayout.LEFT));
		this.messwerte = messwerte;
		this.eingaben = eingaben;
		this.inpol = inpol;
		
		// Zum späteren automatisieren Aktualisieren beim QueryControl anmelden:
		eingaben.alsOutputRegistrieren(this); // <<<<< HIER
		
		// Panelspezifische Eigenschaften definieren:
		Dimension panel = new Dimension(width, height);
		ContainerHelper.setAllSizes(this, panel);
		setBorder(BorderFactory.createTitledBorder("Ergebnis (Ausgabe der Treffer)"));
		
		// Alle Bestandteile des Panels zeichnen:
		zeichnen();
	}

denk denk...:rtfm:
 
Zuletzt bearbeitet:
mh, also die Informationen im JTextField werden nur geupdated, wenn JTextField.setText(String) aufgerufen wird.
Ich glaube was du gemacht hast, ist folgendens: Du hast in deinem QueryControl infos, die du als String an das JTextField weiter gibst. Das Problem ist, dass wenn du den Text von String änderst, dann wird ein neues String-Objekt erstellt. Also hat QueryControl ein neues String-Object das du erst an das JTextField weiter geben musst.
 
Ja ich glaube du hast recht.

Also die TextFields werden aus double Werten gespeist. Dies geschieht in dieser zeichnen() Methode von oben. Da sage ich einfach das z.b. double foo = QueryControl.getFoo() (ist nicht statisch habs nur zum besseren verständniss so getippt).

foo wird dann zum String gemacht. und ein TextField wird erstellt. Was muss der buntus nu genau anders machen? 🙂


Edit: ich habe nun zwischenzeitlich die QueryControl auf das AusgabePanel spezifisch umgebaut, damit ich die zeichnen() Methode aufrufen kann +ein paar sysos.

Die double Werte werden neu gesetzt, also aktualisiert. aber die TextFields werden es nicht 😀

*grübel*
 
Zuletzt bearbeitet:
naja, dann haben wir ja schon die richtige stelle gefunden. Ich würde eine Methode bauen, irgendwas wie updateTextFields(); in der die Werte den TextFields zugeordnet werden und dann per textField.setText(text); übergibst du den Text. Dann kannst du auch einfach benutzen wenn du die Textfelder erzeugst. Dann erzeugst du einfach leere TextFields und rufst dann die Methode auf.

Bsp (im ausgabePanel):
Java:
public void updateTextFields(double d1, double d2, double d3) {
textField1.setText(d1 + "");
textField2.setText(d2 + "");
textField3.setText(d4 + "");
}

^^ also so ungefähr
 
Klappt nicht, also wie in deinem beispiel habe ich die textFields als Klasseneigenschaften definiert.
in zeichnen() werden diese dem Panel hinzugefügt. QueryControl führt nun beim aktualisieren die methoden zeichnen() und aktualisieren() des AusgabePanels aus.

Aktualisieren siehe hier: (ehm achte nicht auf die namen der werte, ich hab da einfach nur was anderes reingedonnert^^)
Java:
	@Override
	public void aktualisieren() {
		System.out.println(eingaben.getBreite());
		temperaturTextFeld.setText(Double.toString(eingaben.getBreite()));
		windTextFeld.setText(Integer.toString((int)eingaben.getLaenge()));
	}

So, die Felder bleiben leider leer. Wenn ich in der Methode aktualisieren() jedoch die Werte ausgebe werden die aktuellen Werte ausgegeben. Hmmm. Also da klappt irgendwie nix 😀


Ich gebe dir mal den kompletten Code (Keine sorge Komentare sollten alles erklären):
AusgabePanel:
Java:
/**
 * Erzeugt das AusgabePanel für die Interpolations-Treffer:
 * 
 * @author zensiert :D
 *
 */
public class JPanel_Ergebnis extends PanelModul {
	private static final long serialVersionUID = -3393429742634142052L;

	private HashSet<Messwert> messwerte;
	private QueryControl eingaben;
	private Interpolator inpol;

	// Felder zum aktualisieren:
	private JTextField temperaturTextFeld;
	private JTextField windTextFeld;
	
	public JPanel_Ergebnis(String titel, int width, int height, HashSet<Messwert> messwerte, QueryControl eingaben, Interpolator inpol) {
		// Eigenschaften definieren:
		super(titel, width, height);
		this.messwerte = messwerte;
		this.eingaben = eingaben;
		this.inpol = inpol;
		
		// Zum späteren automatisieren Aktualisieren beim QueryControl anmelden:
		eingaben.alsOutputRegistrieren(this);
		
		// Alle Bestandteile des Panels zeichnen:
		zeichnen();
	}

	@Override
	public void zeichnen() {
		// Hier kommt alles rein (damit alles schön oben links ist):
		JPanel p = new JPanel(new GridBagLayout());
		GridBagConstraints grid = new GridBagConstraints();
		this.add(p);
		
		/*
		 * Größen für die Inhalte festlegen:
		 */
		Dimension label1 = new Dimension(100, 20); // erste Spalte
		Dimension label2 = new Dimension(300, 20); // zweite Spalte
		Dimension textFeld = new Dimension(50, 20);
	
		/*
		 * Erste Zeile:
		 */
		JLabel temperaturLabel = ContainerHelper.createJLabel("Temperatur", 0, 0, 1, 1, grid, label1);
		p.add(temperaturLabel, grid);
		
		JLabel nachbarnLabel = ContainerHelper.createJLabel("Einbezogene Nachbarwerte", 1, 0, 1, 1, grid, label2);
		p.add(nachbarnLabel, grid);
		
		
		/*
		 * Zweite Zeile:
		 */
		int zeilenhoehe = 130;
		
		// Temperatur Text-Feld:
		temperaturTextFeld = ContainerHelper.createJTextField("", 0, 1, 1, 1, grid, textFeld);
		p.add(temperaturTextFeld, grid);
		
		// Das ist das Ausgabe-Panel:
		JPanel trefferAusgabe = new JPanel(new GridBagLayout());
		ContainerHelper.setAllSizes(trefferAusgabe, new Dimension(550, zeilenhoehe));
		grid.gridx = 1;
		grid.gridy = 1;
		grid.gridwidth = 1;
		grid.gridheight = 10;
		grid.anchor = GridBagConstraints.NORTHWEST;
		generateSpalte2(trefferAusgabe);
		p.add(trefferAusgabe, grid);
		
		
		/*
		 * Dritte Zeile (Windstärke-Label):
		 */
		JLabel windLabel = ContainerHelper.createJLabel("Windstärke", 0, 2, 1, 1, grid, label1);
		p.add(windLabel, grid);
		
	
		/*
		 * Vierte Zeile (Windstärke Text-Feld):
		 */
		windTextFeld = ContainerHelper.createJTextField("", 0, 3, 1, 1, grid, textFeld);
		p.add(windTextFeld, grid);
	}
	
	@Override
	public void aktualisieren() {
		System.out.println(eingaben.getBreite());
		temperaturTextFeld.setText(Double.toString(eingaben.getBreite()));
		windTextFeld.setText(Integer.toString((int)eingaben.getLaenge()));
	}

	private void generateSpalte2(JPanel p) {
		
		p.setBackground(Color.RED);
		GridBagConstraints grid = new GridBagConstraints();
		
		// TODO Auto-generated method stub
		
	}
}


QueryControl:
Java:
/**
 * Hier werden die Benutzereingaben gespeichert. Sehr ähnlich dem Messwert-
 * Objekt, verfügt jeduch nicht über die selben Eigenscahften. Außerdem verfügt
 * diese Klasse über die möglichkeit Panels zu registrieren und auf wunsch zu
 * aktualisieren:
 * 
 * @author zensiert :D
 * 
 */
public class QueryControl {
	private double breite;
	private double laenge;
	private Calendar zeitpunkt;
	private int interPolationsNachbarn;
	private HashSet<PanelModul> outputPanels = new HashSet<PanelModul>();

	public QueryControl(double breite, double laenge, Calendar zeitpunkt, int interPolationsNachbarn) {
		this.breite = breite;
		this.laenge = laenge;
		this.zeitpunkt = zeitpunkt;
		this.interPolationsNachbarn = interPolationsNachbarn;
	}

	/**
	 * Über diese Methode können sich Output PanelModuls registrieren.
	 * Registrierte Panels werden automatisch zum Aktualisieren aufgefordert
	 * wenn sich die Werte der QueryControl verändern:
	 * 
	 * @param panel
	 */
	public void alsOutputRegistrieren(PanelModul panel) {
		outputPanels.add(panel);
	}
	
	/**
	 * Aktualisiert die Output Panels. Diese Methode wird von den Settern dieser
	 * Klasse automatisch ausgeführt (Also ergänzen wenn nötig!). Damit bleiben
	 * die Ausgabepanele stets aktuell zu den Benutzereingaben:
	 * @return
	 */
	private void aktualisiereOutputPanels() {
		Iterator<PanelModul> it = outputPanels.iterator();
		while (it.hasNext()) {
			PanelModul panel = it.next();
			panel.zeichnen();
			panel.aktualisieren();
		}
	}

	/*
	 * GETTER:
	 */
	
	public double getBreite() {
		return breite;
	}

	public double getLaenge() {
		return laenge;
	}

	public Calendar getZeitpunkt() {
		return zeitpunkt;
	}

	public int getInterPolationsNachbarn() {
		return interPolationsNachbarn;
	}

	/*
	 * SETTER:
	 */
	
	public void setBreite(double breite) {
		this.breite = breite;
		aktualisiereOutputPanels();
	}

	public void setLaenge(double laenge) {
		this.laenge = laenge;
		aktualisiereOutputPanels();
	}

	public void setZeitpunkt(Calendar zeitpunkt) {
		this.zeitpunkt = zeitpunkt;
		aktualisiereOutputPanels();
	}

	public void setInterPolationsNachbarn(int interPolationsNachbarn) {
		this.interPolationsNachbarn = interPolationsNachbarn;
		aktualisiereOutputPanels();
	}
}
 
Zuletzt bearbeitet:
ich bin mir nicht sicher, aber hau hinterher mal ein repaint() drüber. eigentlich sollte das nichts zur sache tun. du kannst dann mal noch folgendes Testen:

Java:
System.out.println(windTextFeld.getText());

ob die Textfelder überhaupt der String erreicht. Weil wenn der ankommt, dann kann der fehler nur noch beim Aktualisieren der graphischen Elemente liegen.
 
Danke für den Vorschlag.

Das repaint hat leider nichts gebracht.
Wenn ich getText() ausgebe bekomme ich sogar den aktuellen Wert.
Hm, also es wir einfach nicht neu gezeichnet denke ich mal.

Die Reihenfolge von zeichnen() und aktualisieren() zu vertauschen führt dazu, das der wert nur ein einziges mal aktualisiert wird. Hmmm :autsch:
 
Zuletzt bearbeitet:
mh. also das ist echt seltsam. wenn du willst kannst du mir mal den ganzen code anhängen und dann schau ich mal was ich machen kann. einfach mal die *.java datein zippen und mit an den beitrag hängen. das geht glaube ich einfacher
 
Oh, also ich habe mal list() aufgerufen vom Panel und hm siehe da es werden nach jeder Datenveränderung mehr Contents angezeigt. scheint mit dem

Java:
// Hier kommt alles rein (damit alles schön oben links ist):
		JPanel p = new JPanel(new GridBagLayout());
		GridBagConstraints grid = new GridBagConstraints();
		this.add(p);

zusammenzuhängen. Ehm ich schicks dir glaub ich, aber ich glaube es leigt an dem hier. Deswegen behalt ich das mal als Plan B.

Kann ich irgendwie sagen das alle add() Befehle rückgängig gemacht werden sollen?
 
Argh! ^^
Klappt nix, ich hab dir mal ne PN mit dem Link geschickt.

Hab da alles rausgeworfen was irgendwie ging für dich 😀
Du kannst das direkt in eclipse importieren (ich hoffe mal einfach du nutzt das).
 
Zuletzt bearbeitet:
Also:
Im Querycontrol musst du folgende Methode wie folgt ändern:

Java:
private void aktualisiereOutputPanels() {
		Iterator<PanelModul> it = outputPanels.iterator();
		while (it.hasNext()) {
			PanelModul panel = it.next();
			panel.list();
			panel.aktualisieren();
		}
	}

du hast beim zeichnen immer wieder ein neues Textfeld erstellt, das dann natürlich leer war.
schöne nacht noch 😉
 

Zurück
Oben