Portal > Foren > Java > Desktop-Applikationen und Grafik > Textfelder auf verschiedenen Tabs per Observer synchronisieren
Antwort
 
Themen-Optionen Thema durchsuchen
Alt 05.12.2005, 16:06 Nach oben    #1
Benutzer
 
Registriert seit: 05.12.2005
Beiträge: 62
Standard Textfelder auf verschiedenen Tabs per Observer synchronisieren

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:
Zitat:
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(Unk nown 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
Zitat:
java.lang.IllegalStateException: Attempt to mutate in notification
at javax.swing.text.AbstractDocument.writeLock(Unknow n 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
Code:
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
Code:
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
Code:
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
Sayang

P. S. Benutze die 1.4.2_10
Sayang ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 05.12.2005, 17:06 Nach oben    #2
Projektleiter
 
Registriert seit: 30.11.2005
Ort: Bottrop
Beiträge: 1.160
Standard

Um zwei JTextField mit dem gleichen Inhalt zu realisieren empfiehlt es sich immer, direkt mit dem Document-Interface zu arbeiten.

Soll heißen:
Code:
textfield2.setDocument(textfield1.getDocument())
Dann wird das Filtern der Eingabe häufig im Document (oder via DocumentFilter) selbst realisiert (ich meine mich zu erinnern, dass es dazu ein Tutorial von Sun gab).
Alternativ kann man's auch über einen DocumentListener realisieren. Der CaretListener ist definitiv falsch.

Außerdem noch folgendes: Du solltest beim überprüfen die mögliche Runtime-Exception abfangen und allgemein vorher überprüfen, ob überhaupt etwas im Textfeld steht (if(!"".equals(textfield1.getText()))...)
__________________
Patrick Gotthardts Weblog.
pago ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 05.12.2005, 19:14 Nach oben    #3
Benutzer
 
Registriert seit: 05.12.2005
Beiträge: 62
Standard

Vielen Dank erstmal. Werde das dann mal mit dem Document Interface ausprobieren. Aber dass diese (erste) Exception geworfen wird, wundert mich dennoch... naja, mal schauen was passiert.

Danke erstmal
Sayang
Sayang ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Antwort

Lesezeichen


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind an
PingBacks sind an
RefBacks sind aus

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
SessionID per Url auf Portal-Seite Artemis Fragen ans Team 7 09.07.2007 20:25
Apache-Zugriffskontrolle auf eine Datei per .htaccess: 500er Artemis Tools, Server, Betriebssysteme 4 23.03.2007 21:29
[PHP] Wie übergebe ich Daten per URL? Ben Tutorials 0 05.12.2004 14:36
Auf ein Canvas Objekt per Mouseevents Linien Zeichnen schärple Desktop-Applikationen und Grafik 6 12.06.2004 17:42


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:29 Uhr.


Powered by vBulletin® Version 3.7.4 (Deutsch)
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45