2010-12-03 7 views
0

Ich habe eine Java Swing-Anwendung, die über viele JTextFields und ein Datamodel verfügt.JTextField mit Model (on focusLost) verwenden und Aktionen mit Modelldaten ausführen

Beim Verlassen der Textfelder (Fokus verloren) wird der Text in das Modell geschrieben. So weit, ist es gut.

Es gibt JMenu-Aktionen, die Daten aus dem Modell lesen und an den Server senden.

Das Problem ist, dass der "Fokus verloren" nicht ausgelöst wird, wenn die Menüaktion mit dem Beschleuniger ausgeführt wird. Die Aktionen lesen und übertragen den alten Wert aus dem Datenmodell. .

Es gibt viele Möglichkeiten, dies zu beheben ...? Haben Sie Vorschläge, wie Sie das lösen?

Was für mich nicht funktioniert:

  • Schreiben auf jedem Tastendruck zu modellieren (via Document Listener): nicht verwendbar, nur Textfeld (Fokus verloren) beim Verlassen schreiben soll. Der Text wird (teuer) nach dem Schreiben in das Modell ausgewertet - kann nicht nach jedem Tastendruck ausgeführt werden.
  • Umgang mit dem Schreiben zu modellieren in jeder Aktion. Ca. 500 Textfelder und ca. 100 Aktionen. Diffucult zu passen, ohne etwas zu vergessen.

Runnable Demo-Code:

package swingmodel; 

import java.awt.FlowLayout; 
import java.awt.event.*; 

import javax.swing.*; 

/** 
* Simple Demo Problem. Enter a Text in the first Textfield and press ALT-T. The 
* focus listener did no run, therefore the old value from model is displayed. 
*/ 
public class TextDemoOnMenu extends JPanel { 
    private Model model; 

    public TextDemoOnMenu() { 
    super(new FlowLayout()); 

    model = new Model(); 
    MyTextField textField = new MyTextField(20, model); 
    add(textField); 
    add(new JTextField(5)); 

    } 

    class MyTextField extends JTextField { 

    private Model model; 

    public MyTextField(int arg, Model model) { 
     super(arg); 
     this.model = model; 
     addFocusListener(new FocusAdapter() { 
     @Override 
     public void focusLost(FocusEvent e) { 
      System.out.println("focus lost"); 
      writeToModel(); 
     } 
     }); 
    } 

    public void writeToModel() { 
     this.model.setText(getText()); 
    } 
    } 

    class ShowModelTextAction extends AbstractAction { 

    public ShowModelTextAction(String string) { 
     super(string); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     String message = "text is: " + model.getText(); 
     JOptionPane.showMessageDialog(TextDemoOnMenu.this, message); 
    } 
    } 

    class Model { 
    private String text; 

    void setText(String t) { 
     text = t; 
    } 

    public String getText() { 
     return text; 
    } 
    } 

    private void createAndShowGUI() { 
    // Create and set up the window. 
    JFrame frame = new JFrame("TextDemo"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    // Add contents to the window. 
    frame.add(this); 

    Action action = new ShowModelTextAction("show text"); 
    JMenuBar menuBar = new JMenuBar(); 
    JMenu menu = new JMenu("My Menu"); 
    menuBar.add(menu); 
    JMenuItem menuItem = new JMenuItem("show text"); 
    menuItem.setAction(action); 
    menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, ActionEvent.ALT_MASK)); 
    menu.add(menuItem); 
    frame.setJMenuBar(menuBar); 

    // Display the window. 
    frame.setSize(400, 200); 
    frame.setVisible(true); 
    } 


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

} 

Antwort

2

Sie können alle Ihre Aktionen ändern, um den KeyboardFocusManager zu verwenden. Sie würden die aktuelle Komponente erhalten, die den Fokus hat. Wenn es sich um eines Ihrer benutzerdefinierten Textfelder handelt, können Sie vor der Verarbeitung der Aktion eine Aktualisierung des Modells erzwingen.

Der Text (teuer) wird ausgewertet, nachdem sie auf das Modell

auch schreiben, es klingt wie Sie auch focusGained Handhabung werden sollte. Dann können Sie den Originaltext speichern und einen Vergleich zum verlorenen Text durchführen, bevor Sie das Modell automatisch aktualisieren. (Was ist, wenn jemand nur alle Textfelder durchsucht?).

+0

danke, das hat geholfen! ;) – Synox

1

erstellen Dirty-Flag für jede Textfield. Wenn das Ereignis save eintritt, können Sie das Modell mit einem beliebigen schmutzigen TextField aktualisieren.

Wenn Sie besorgt sind, dass Sie "vergessen", dies für einen bestimmten TextField zu tun, ist es Ihre Verwaltung der Textfelder, die das Problem ist. Sie sollten eine Factory-Methode für sie haben, die sie richtig einrichtet und schmutzige Flags für sie erstellt.

Mein anderer Vorschlag ist, wenn diese speichern Aktion auftritt, fordern Sie den Fokus auf eine versteckte Komponente, um die FocusLost auf dem Textfeld auszulösen. Wenn der Speichervorgang abgeschlossen ist, geben Sie den Fokus wieder an den vorherigen Besitzer zurück.