2016-04-01 7 views
0

Ich habe ein Panel mit ein paar Textfeldern und einem editierbaren JComboBox verwendet, um eine Suche durchzuführen. Ich möchte, dass alle so funktionieren, als würde ich die Suchschaltfläche darunter drücken, wenn ich die Eingabetaste drücke. Dies funktioniert gut für eine JTextField mit einer ActionListener. Ich möchte jedoch nur die JComboBox die Suche starten, wenn Enter gedrückt wird und die Dropdown-Liste nicht angezeigt wird. I.e. Wenn der Benutzer die Eingabetaste drückt, um eine Option im Dropdown auszuwählen, sollte nichts passieren.Editierbare JComboBox: Bestimmen, ob die Eingabetaste gedrückt wird, während sie in der Dropdown-Auswahl ignoriert wird?

Wie würde ich dieses Verhalten erreichen?

Ich habe versucht zu überprüfen getActionCommand() und es zeigt entweder "comboBoxEdited" oder "comboBoxChanged", wenn das Ereignis ausgelöst wird. "comboBoxEdited" wird ausgelöst, wenn nach dem Auswählen einer Option die Eingabetaste gedrückt wird und wenn Sie im bearbeitbaren Feld die Eingabetaste drücken. "comboBoxChanged" wird ausgelöst, wenn zwischen den Optionen gewechselt wird, sowie kurz vor "comboBoxEdited", wenn nach dem Bearbeiten des Textes Enter gedrückt wird.

Ich versuchte einen hässlichen Hack, wo ich die vorherige ActionCommand speichern, aber es ist nicht perfekt, da der Benutzer zweimal nach der Eingabe von Text manuell drücken muss.

public void actionPerformed(ActionEvent e) { 
    if (e.getActionCommand().equals("comboBoxEdited") && 
     !combohack.equals("comboBoxChanged")) { 

     combohack=""; 
     //PERFORM SEARCH! 
    } 
    combohack=e.getActionCommand(); 
} 

Ich versuchte weiterhin meinen Hack noch hässlicher zu machen, indem ein KeyListener als auch das Hinzufügen der Zeichenfolge zurückgesetzt, wenn tatsächliche Buchstaben, wo gedrückt, aber das half nicht.

Irgendwelche Ideen?

+0

Was ist der Unterschied zwischen dem Benutzer, der während der Bearbeitung des Feldes [Enter] drückt, und dem Benutzer, der ein Element aus dem Drop-down-Menü auswählt? – MadProgrammer

+0

@MadProgrammer Der Benutzer möchte vielleicht etwas in andere Suchfelder eingeben, indem er auf diese ein Tabstopp einlegt, bevor die Suche ausgeführt werden soll. Es ist normal für die meisten Leute, [Enter] zu drücken, wenn sie eine Option mit den Pfeiltasten auswählen (obwohl Sie [Tab] drücken könnten). Die Anwendung ist nicht für die Verwendung der Maus gedacht. – Kilgore

Antwort

1

Okay, das ist ein wenig plump, aber das, was tut, ist ersetzt die KeyEvent.VK_ENTERAction mit unserem eigenen Action

Also im Grunde, wenn der Benutzer die Enter-Taste drückt, aus Action mitgeteilt wird, aber die Combo-Box ist nicht (so die JComboBox wird kein ActionEvent für sie auslösen - aber Wille zur Auswahl Änderungen)

import java.awt.Component; 
import java.awt.EventQueue; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import javax.swing.AbstractAction; 
import javax.swing.ActionMap; 
import javax.swing.ComboBoxEditor; 
import javax.swing.InputMap; 
import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 
import javax.swing.KeyStroke; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     public TestPane() { 
      setLayout(new GridBagLayout()); 
      final JComboBox<String> cb = new JComboBox<>(new String[]{"Apples", "Bananas", "Pears"}); 
      cb.setEditable(true); 
      SimpleComboBoxEditor editor = new SimpleComboBoxEditor(); 
      InputMap im = editor.getInputMap(); 
      ActionMap am = editor.getActionMap(); 
      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "enter"); 
      am.put("enter", new AbstractAction() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        if (!cb.isPopupVisible()) { 
         System.out.println("Editor did action"); 
        } 
        cb.hidePopup(); 
       } 
      }); 
      cb.setEditor(editor); 
      cb.addActionListener(new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        System.out.println("Combobox did action"); 
       } 
      }); 
      add(cb); 
     } 

     public class SimpleComboBoxEditor extends JTextField implements ComboBoxEditor { 

      @Override 
      public Component getEditorComponent() { 
       return this; 
      } 

      @Override 
      public void setItem(Object anObject) { 
       if (anObject != null) { 
        setText(anObject.toString()); 
       } else { 
        setText(null); 
       } 
      } 

      @Override 
      public Object getItem() { 
       return getText(); 
      } 

     } 

    } 

} 

Danke für die Mühe ! Es funktioniert nicht wirklich so, wie ich es möchte. Das Ereignis wird weiterhin mit "comboBoxEdited" ausgelöst, wenn [Enter] gedrückt wird, um das markierte Element auszuwählen, anstatt nur das Dropdown-Menü zu schließen und den ausgewählten Text im Editor zu belassen. Es sollte das Ereignis nur auslösen, wenn das Dropdown-Menü geschlossen ist und der Benutzer [Enter] drückt. Also [Enter], um einen Gegenstand auszuwählen, [Enter] erneut, um die Aktion auszulösen.

Also, er habe endlich den Code auf einem Windows-Rechner laufen zu lassen und im Grunde genommen in den Action für den Schlüssel Bindung, machte ich einen Scheck für isPopupVisible, wenn es nicht ist, wird es der „Editor tat Aktion“ drucken Ereignis, sonst tut es nichts

+0

Danke für die Mühe! Es funktioniert nicht wirklich so, wie ich es möchte. Es wird weiterhin das Ereignis mit "comboBoxEdited" ausgelöst, wenn [Enter] gedrückt wird, um das markierte Element auszuwählen, anstatt nur das Dropdown-Menü zu schließen und den ausgewählten Text im Editor zu belassen. Es sollte das Ereignis nur auslösen, wenn das Dropdown-Menü geschlossen ist und der Benutzer [Enter] drückt. Also [Enter], um einen Gegenstand auszuwählen, [Enter] erneut, um die Aktion auszulösen. – Kilgore

+0

Dann verwenden Sie den ersten Ansatz und nur auf das Feld selbst reagieren – MadProgrammer

+0

Ich benutze einen Mac, so kann ich nicht durch die Optionen des Ablegen Pfeil und drücken Sie "Enter": P – MadProgrammer

-1

es ist eigentlich eine recht einfache und elegante Lösung:

combo.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() { 
    @Override 
    public void keyPressed(KeyEvent e) { 
     if (e.getKeyCode()==KeyEvent.VK_ENTER && !combo.isPopupVisible()) { 
      System.out.println("SEARCH!"); 
     } 
    } 
}); 

Beachten sie, dass die KeyListener nicht, wenn auf die direkt JComboBox hinzugefügt arbeiten, sondern muss seine hinzugefügt werden EditorComponent .

+0

' KeyListener' ist nie die Lösung, vor allem im Umgang mit Textkomponenten, gibt es nur zu viele Dinge, die falsch und zu vielen besseren Möglichkeiten, um das Problem zu lösen – MadProgrammer

+0

@MadProgrammer Mind erklären was könnte falsch laufen oder auf eine Quelle zeigen? – Kilgore

+0

Als allgemeine Regel gilt, dass der Schlüssel-Listener in fast allen Fällen eine schlechte Wahl ist. Sie können nicht die Reihenfolge garantieren, in der Ereignisse zugestellt werden, oder wenn der Schlüssel irgendwann in der Ereigniskette verbraucht wird, wenn das Feld möglicherweise aktualisiert wurde. Als allgemeine Faustregel sollten Sie Tastenkombinationen, DocumentFilter oder DocumentListener über KeyListener verwenden, je nachdem, was Sie erreichen möchten – MadProgrammer

Verwandte Themen