Gibt es eine einfache Möglichkeit, das Verhalten einer Java / Swing Kontrolle, wenn es den Fokus erhält zu ändern?

StackOverflow https://stackoverflow.com/questions/66455

  •  09-06-2019
  •  | 
  •  

Frage

Für die meisten GUIs ich verwendet habe, wenn ein Steuerelement, das Text enthält den Fokus erhält, wird der gesamte Inhalt der Steuerung ausgewählt werden. Das bedeutet, wenn Sie einfach mit der Eingabe beginnen, Sie vollständig die früheren Inhalte ersetzen.

Beispiel: Sie haben Spin-Steuerung, die mit dem Wert Null initialisiert wird. Sie Tab, um es und geben Sie „1“ Der Wert in der Steuerung ist jetzt 1.

Mit Swing, dies nicht geschieht. Der Text in der Steuerung nicht ausgewählt, und die Karat erscheinen an einem Ende oder einem anderen des bestehenden Textes. Fortsetzung des obigen Beispiel:

Mit einem Swing-JSpinner, wenn Sie mit der Tabulatortaste zur Spin-Steuerung, die Karat auf der linken Seite. Sie geben „1“ und den Wert in der Steuerung ist jetzt 10.

Das treibt mich (und meine Benutzer) auf eine Wand, und ich möchte es ändern. Noch wichtiger ist, würde ich es gerne global ändern, um das neue Verhalten gilt für JTextField, JPasswordField, JFormattedTextField, JTextArea, JComboBox, JSpinner, und so weiter. Der einzige Weg, die ich gefunden habe, dies zu tun, um eine FocusAdapter zu jedem Steuerelement hinzuzufügen und die focusGained () -Methode außer Kraft setzen, das Richtige zu tun [tm].

Es muss sein, eine leichte und weniger zerbrechlich Art und Weise. Bitte?

EDIT: Eine zusätzliche Information für diesen speziellen Fall. Die Form mit denen ich arbeite wurde mit Idea Formular-Designer generiert. Das heißt, ich normalerweise nicht tatsächlich den Code schreiben, um die Komponenten zu erstellen. Es ist möglich, Idee zu sagen, dass Sie wollen, dass sie sich selbst erstellen, aber das ist ein Streit Ich mag würde zu vermeiden.

Motto: Alle guten Programmierer sind grundsätzlich faul

.
War es hilfreich?

Lösung 4

(! Dank)

Nachdem die Antworten zu lesen, so weit habe ich die äußerste JPanel der folgenden Methode:

void addTextFocusSelect(JComponent component){
    if(component instanceof JTextComponent){
        component.addFocusListener(new FocusAdapter() {
                @Override
                public void focusGained(FocusEvent event) {
                    super.focusGained(event);
                    JTextComponent component = (JTextComponent)event.getComponent();
                    // a trick I found on JavaRanch.com
                    // Without this, some components don't honor selectAll
                    component.setText(component.getText());
                    component.selectAll();
                }
            });

    }
    else
    {
        for(Component child: component.getComponents()){
            if(child instanceof JComponent){
                addTextFocusSelect((JComponent) child);
            }
        }
    }
}

Es funktioniert!

Andere Tipps

Als ich dies in der Vergangenheit benötigt habe, habe ich Subklassen der Komponenten erstellt I „Auto-clearing“ Funktionalität auch hinzufügen wollte. zB:

public class AutoClearingTextField extends JTextField {
   final FocusListener AUTO_CLEARING_LISTENER = new FocusListener(){
      @Override
      public void focusLost(FocusEvent e) {
         //onFocusLost(e);
      }

      @Override
      public void focusGained(FocusEvent e) {
         selectAll();
      }
   };

   public AutoClearingTextField(String string) {
      super(string);
      addListener();
   }

   private void addListener() {
      addFocusListener(AUTO_CLEARING_LISTENER);      
   }
}

Das größte Problem ist, dass ich nicht einen „guten“ Weg gefunden habe, um all Standard-Konstrukteure zu erhalten ohne Überschreibungen zu schreiben. Hinzufügen von ihnen, und zwingt einen Anruf zu addListener ist der allgemeinste Ansatz, den ich gefunden habe.

Eine weitere Option ist für ContainerEvents auf einem Top-Level-Container mit einem ContainerListeer zu sehen, das Vorhandensein von neuen Widgets zu erkennen, und fügen Sie Hörer einen entsprechenden Fokus auf der Grundlage der Widgets, die hinzugefügt wurden. (ZB: wenn der Behälter Ereignis durch Zugabe eines TextField- verursacht wird, dann einen Fokus Zuhörer hinzufügen, die weiß, wie man den gesamten Text in einem Textfield zu wählen, und so weiter.) Wenn ein Container hinzugefügt wird, dann müssen Sie rekursiv die ContainerListener hinzufügen zu diesem neuen Unterbehälter als auch.

So oder so, werden Sie nicht mit dem Fokus Zuhörer in Ihrem aktuellen UI-Code Dreck müssen -. Es wird alles kümmert auf einer höheren Ebene getroffen werden

Das habe ich mich nicht versucht (nur in ihm vor einer Weile dabbled), aber man kann wahrscheinlich die aktuelle fokussierte Komponente durch die Verwendung erhalten: KeyboardFocusManager (es gibt eine statische Methode getCurrentKeyboardFocusManager ()) eine Zugabe eines Property zu. Von dort können Sie herausfinden, ob die Komponente eine JTextComponent ist und den gesamten Text auswählen.

Eine separate Klasse, die einen Focuslistener auf die gewünschte Textfeld legt geschrieben werden. Der ganze Fokus Zuhörer tun würde, ist Aufruf selectAll () auf dem Text-Widget, wenn es den Fokus erhält.

public class SelectAllListener implements FocusListener {
  private static INSTANCE = new SelectAllListener();

  public void focusLost(FocusEvent e) { }

  public void focusGained(FocusEvent e) {
    if (e.getSource() instanceof JTextComponent) {  
      ((JTextComponent)e.getSource()).selectAll();
    }
  };

  public static void addSelectAllListener(JTextComponent tc) {
    tc.addFocusListener(INSTANCE);
  }

  public static void removeSelectAllListener(JTextComponent tc) {
    tc.removeFocusListener(INSTANCE);
  }
}

Durch eine JTextComponent als Argument akzeptieren, dieses Verhalten zu JTextArea, JPasswordField, und alle anderen Textbearbeitung Komponenten direkt hinzugefügt werden können. Auf diese Weise können auch die Klasse wählen Sie alle in editierbare Combo-Boxen und JSpinners hinzufügen, wo Ihr die Kontrolle über den Texteditor Komponente geringer ausfallen können. Convenience-Methoden können hinzugefügt werden:

public static void addSelectAllListener(JSpinner spin) {
  if (spin.getEditor() instanceof JTextComponent) {
    addSelectAllListener((JTextComponent)spin.getEditor());
  }
}

public static void addSelectAllListener(JComboBox combo) {
  JComponent editor = combo.getEditor().getEditorComponent();
  if (editor instanceof JTextComponent) {
    addSelectAllListener((JTextComponent)editor);
  }
}

Auch die Entfernen-Listener-Methoden wahrscheinlich nicht mehr benötigte, da der Hörer keine äußere Verweise auf andere Instanzen enthält, aber sie können hinzugefügt werden, um Code-Reviews zu machen gehen glatter.

Der einzige Weg, ich weiß, ist ein Focuslistener zu erstellen und an Ihre Komponente befestigen. Wenn Sie es möchten alle Focuslistener Komponenten in der Anwendung global sein Sie sich anschauen sollten mit Aspect Oriented Programming (AOP). Mit AOP ist es einmal zu kodieren und Ihren Fokus Zuhörer auf alle in Ihrer Anwendung instanziiert Komponenten anwenden, ohne kopieren und einfügen, die den component.addFocusListener (Hörer) Code in Ihrer Anwendung ..

würde Ihr Aspekt haben die Schaffung eines JComponent (oder den Unterklassen Sie dieses Verhalten hinzufügen möchten) abzufangen und den Fokus Zuhörer auf die neu erstellte Instanz hinzufügen. Der AOP Ansatz ist besser als Kopieren und Einfügen der Focuslistener, um Ihren gesamten Code, weil Sie alles in einem einzigen Stück Code halten, und keine Wartung Alptraum erstellen, sobald Sie sich entscheiden, wie das Entfernen den Zuhörers Ihr globales Verhalten ändern für JSpinners.

Es gibt viele AOP-Frameworks da draußen zur Auswahl. Ich mag JBossAOP , da sie 100% pure Java, aber Sie könnten auf einen Blick nehmen wie AspectJ .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top