JAVA: Textfelder auf verschiedenen Tabs per Observer synchronisieren

  • #1
M

Michael_B

Bekanntes Mitglied
Themenersteller
Dabei seit
21.09.2002
Beiträge
860
Reaktionspunkte
0
Ort
Köln
Hi,

ich schreib derzeit an einer GUI, die u. a. auf mehreren Tabs eines JTabbedPane jeweils die gleichen JTextField-Komponenten hat. Änderungen an diesen Werten möchte ich quasi zum Zeitpunkt der Änderung (also nicht erst nach der Eingabe, sondern nach der Eingabe eines Zeichens) überwachen - da hier nur ganze Zahlen eingegeben werden dürften.
Dazu benutze ich den EventListener javax.swing.event.CaretListener der auf eine Veränderung des Cursors hört.
Außerdem sollen die Werte in den Textfeldern AUF BEIDEN Tabs immer die gleichen sein; es soll also eine Änderung eines Wertes auf Tab1 automatisch auch auf Tab2 gemacht werden. Hierzu möchte ich das Beobachter-Pattern nutzen und bediene mich also dem Interface Observer und der Klasse Observable.
Die Datenhaltung geschieht in der Klasse Properties, die Observable erweitert. Die Panels, die in die Tabs des JTabbedPane eingebaut werden, sind InputPanels und bekommen bei Konstruktion die in der Haupt-Klasse (Main) erzeugte Instanz von Properties übergeben. InputPanel implementiert Observer und meldet sich bei der Properties-Instanz auch als Observer an. Ebenfalls existiert die zur Implementierung notwendige Methode update(Observable o, Object arg).

Klicke ich nun in eines der Eingabefelder, wird ein CaretEvent gefeuert. In der Methode, die das Event bearbeiten soll (caretUpdate(CaretEvent e)) setze ich die entsprechenden Werte der Properties-Instanz per entsprechender set-Methode (logischerweise von String auf int geparsed). Die set-Methode der Klasse Properties setzt den entsprechenden Wert, setzt ein Flag, dass etwas geändert wurde (setChanged()), und benachrichtigt danach seine Beobachter (notifyObservers()). Soweit die Theorie... in der Praxis bekomme ich jedoch schon bei Klick in das Eingabefeld folgende Exception:
java.lang.NumberFormatException: For input string:
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at spielwiese.InputPanel.caretUpdate(InputPanel.java:49)
...
Da das Textfeld jedoch vor dem Klick in selbiges schon einen Wert hatte (in diesem Beispiel 20), verstehe ich nicht, warum der String, den ich zu einem int parsen möchte, leer ist.
Gebe ich nun an der Stelle eine weitere 0 ein (mache also aus der 20 eine 200) bekomme ich
java.lang.IllegalStateException: Attempt to mutate in notification
at javax.swing.text.AbstractDocument.writeLock(Unknown Source)
at javax.swing.text.AbstractDocument.replace(Unknown Source)
at javax.swing.text.JTextComponent.setText(Unknown Source)
at spielwiese.InputPanel.update(InputPanel.java:44)
at java.util.Observable.notifyObservers(Unknown Source)
at java.util.Observable.notifyObservers(Unknown Source)
at spielwiese.Properties.setValue1(Properties.java:14)
at spielwiese.InputPanel.caretUpdate(InputPanel.java:49)
...

Möglich, dass der CaretListener für meine Zwecke nicht der richtige ist. Wenn ihr da einen Vorschlag habt, immer her damit. Ansonsten wüsste ich gerne, warum der da versucht, nen leeren String zu parsen :-[

Hier noch der Code der 3 Klassen zum Nachvollziehen:

Main.java
package spielwiese;
import javax.swing.JTabbedPane;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JComponent;
import java.awt.BorderLayout;
import java.awt.GridLayout;

public class Main extends JPanel {
public Main() {
super(new GridLayout(1, 1));

spielwiese.Properties p = new spielwiese.Properties();

JTabbedPane tabbedPane = new JTabbedPane();

InputPanel pnl1 = new InputPanel(p);
tabbedPane.addTab(Tab 1, null, pnl1, Werte kann man hier...);

InputPanel pnl2 = new InputPanel(p);
tabbedPane.addTab(Tab 2, null, pnl2, ... und hier eingeben);

add(tabbedPane);

System.out.println(Anzahl Observers: +p.countObservers());
}

private static void createAndShowGUI() {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame(TextField Observer Test);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new Main();
newContentPane.setOpaque(true);
frame.getContentPane().add(newContentPane, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}

public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

Properties.java
package spielwiese;
import java.util.Observable;

public class Properties extends Observable {

private int value1 = 20;
private int value2 = 7;

public Properties() {}

public int getValue1() { return this.value1; }
public int getValue2() { return this.value2; }

public void setValue1(int n) { this.value1 = n; this.setChanged(); this.notifyObservers(); }
public void setValue2(int n) { this.value2 = n; this.setChanged(); this.notifyObservers();}
}

InputPanel.java
package spielwiese;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.util.Observer;
import java.util.Observable;

public class InputPanel extends JPanel implements CaretListener, Observer {

private spielwiese.Properties p;
private JTextField tf1, tf2;
private JLabel lbl1, lbl2;

public InputPanel() {
this(new spielwiese.Properties());
}

public InputPanel(spielwiese.Properties p) {
this.p = p;
this.p.addObserver(this);

this.lbl1 = new JLabel(Value 1:);
this.lbl2 = new JLabel(Value 2:);

this.tf1 = new JTextField(p.getValue1()+);
this.tf2 = new JTextField(p.getValue2()+);

this.tf1.addCaretListener(this);
this.tf2.addCaretListener(this);

this.setLayout(new GridLayout(2,2));

this.add(this.lbl1);
this.add(this.tf1);
this.add(this.lbl2);
this.add(this.tf2);

this.setPreferredSize(new Dimension(250,60));
}

public void update(Observable o, Object arg) {
this.tf1.setText(p.getValue1()+);
this.tf2.setText(p.getValue2()+);
}

public void caretUpdate(CaretEvent e) {
this.p.setValue1(Integer.parseInt(this.tf1.getText()));
this.p.setValue2(Integer.parseInt(this.tf2.getText()));
}

}

Bin über jeden Tipp dankbar...

Lg
Michael
 
Thema:

JAVA: Textfelder auf verschiedenen Tabs per Observer synchronisieren

ANGEBOTE & SPONSOREN

Statistik des Forums

Themen
113.840
Beiträge
707.963
Mitglieder
51.494
Neuestes Mitglied
Flensburg45
Oben