Java – stop JPopupMenu stealing focus

I have a jtextfield, and I want to suggest that the results match the user's input I show these suggestions in JList included in JPopupMenu

However, when the pop-up menu is opened programmatically through show (component invoker, int x, int y), the focus will be obtained from jtextfield

Strangely, if I call setvisible (true) instead, the focus will not be stolen; But then the JPopupMenu is not attached to any panels, and when the box is opened and the application is minimized, it will remain drawn on the window

I also tried to use requestfocus () to reset the focus to jtextfield, but I had to use swingutilities Invoker () restores the caret position and invokes the latter to give the user a small margin to / overwrite / or do other unpredictable things with the existing content

My code is valid:

JTextField field = new JTextField();
jpopupmenu menu = new jpopupmenu();

field.addKeyListener(new KeyAdapter() {
    public void keyTyped(KeyEvent e) {
        JList list = getAListOfResults();

        menu.add(list);
        menu.show(field,field.getHeight());
    }
});

Can anyone suggest the best way to programmatically display JPopupMenu while retaining attention to jtextfield?

Solution

The technical answer is to set the pop-up focus attribute to false:

popup.setFocusable(false);

This means that textfield must take over all keyboard and mouse triggered operations normally handled by the list itself. Sosmetting is similar to:

final JList list = new JList(Locale.getAvailableLocales());
final jpopupmenu popup = new jpopupmenu();
popup.add(new JScrollPane(list));
popup.setFocusable(false);
final JTextField field = new JTextField(20);
Action down = new AbstractAction("nextElement") {

    @Override
    public void actionPerformed(ActionEvent e) {
       int next = Math.min(list.getSelectedIndex() + 1,list.getModel().getSize() - 1);
       list.setSelectedIndex(next);
       list.ensureIndexIsVisible(next);
    }
};
field.getActionMap().put("nextElement",down);
field.getInputMap().put(
        Keystroke.getKeystroke("DOWN"),"nextElement");

Because of your context and JCombo@R_658_2419 @Very similar, you can consider viewing BasicCombo@R_658_2419 @The source of UI and basiccombopopup

edit

Just for fun, the following does not answer the focus question: -) but demonstrates how to use sortable / filterable jxlist to display the options corresponding to typed text in the drop-down list (here to start the rule)

// instantiate a sortable JXList
final JXList list = new JXList(Locale.getAvailableLocales(),true);
list.setSortOrder(SortOrder.ASCENDING);

final jpopupmenu popup = new jpopupmenu();
popup.add(new JScrollPane(list));
popup.setFocusable(false);
final JTextField field = new JTextField(20);

// instantiate a PatternModel to map text --> pattern 
final PatternModel model = new PatternModel();
model.setMatchRule(PatternModel.MATCH_RULE_STARTSWITH);
// listener which to update the list's RowFilter on changes to the model's pattern property  
Propertychangelistener modelListener = new Propertychangelistener() {

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if ("pattern".equals(evt.getPropertyName())) {
            updateFilter((Pattern) evt.getNewValue());
        }
    }

    private void updateFilter(Pattern newValue) {
        RowFilter<Object,Integer> filter = null;
        if (newValue != null) {
            filter = RowFilters.regexFilter(newValue);
        }
        list.setRowFilter(filter);
    }
};
model.addPropertychangelistener(modelListener);

// DocumentListener to update the model's rawtext property on changes to the field
DocumentListener documentListener = new DocumentListener() {

    @Override
    public void removeUpdate(DocumentEvent e) {
        updateAfterDocumentChange();
    }

    @Override
    public void insertUpdate(DocumentEvent e) {
        updateAfterDocumentChange();
    }

    private void updateAfterDocumentChange() {
        if (!popup.isVisible()) {
            popup.show(field,field.getHeight());
        } 
        model.setRawText(field.getText());
    }

    @Override
    public void changedUpdate(DocumentEvent e) {
    }
};
field.getDocument().addDocumentListener(documentListener);
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>