首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >阻止JPopupMenu窃取焦点

阻止JPopupMenu窃取焦点
EN

Stack Overflow用户
提问于 2012-04-05 13:48:27
回答 3查看 2.9K关注 0票数 11

我有一个JTextField,希望为其提供与用户输入相匹配的结果。我在一个包含在一个JList中的JPopupMenu中显示这些建议。

但是,当通过show(Component invoker, int x, int y)以编程方式打开弹出菜单时,焦点将从JTextField中移除。

奇怪的是,如果我调用setVisible(true),焦点不会被窃取;但是JPopupMenu不会附加到任何面板上,并且当在打开框时最小化应用程序时,它会保持在窗口上。

我还尝试使用JTextField将焦点重置为requestFocus(),但随后我必须使用SwingUtilities.invokeLater()恢复插入符号位置,而调用的后面部分给用户提供了一点空间来处理现有的内容/覆盖它/或做其他不可预知的事情。

我得到的代码实际上是:

代码语言:javascript
复制
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, 0, field.getHeight());
    }
});

有谁能建议在保持对JPopupMenu的关注的同时,以编程方式显示JTextField的最佳途径?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-04-06 11:38:20

技术上的答案是将弹出窗口的可聚焦属性设置为false:

代码语言:javascript
复制
popup.setFocusable(false);

这意味着textField必须接管通常由列表本身处理的所有键盘和鼠标触发的操作,比如:

代码语言:javascript
复制
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");

由于您的上下文非常类似于JComboBox,您可能会考虑查看BasicComboBoxUI和BasicComboPopup的来源。

编辑

只是为了好玩,下面没有回答焦点问题:-)相反,它演示了如何使用可排序/可过滤的JXList来只显示下拉列表中与类型化文本对应的选项(这里有一个开始- with规则)

代码语言:javascript
复制
// 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, 0, field.getHeight());
        } 
        model.setRawText(field.getText());
    }

    @Override
    public void changedUpdate(DocumentEvent e) {
    }
};
field.getDocument().addDocumentListener(documentListener);
票数 14
EN

Stack Overflow用户

发布于 2012-04-05 17:34:31

它对我来说是向前看的。添加以下内容

field.requestFocus();

之后

代码语言:javascript
复制
 menu.add(list);
 menu.show(field, 0, field.getHeight());

当然,您必须根据JTextField正在发生的情况,为何时隐藏弹出窗口等编写代码。

即;

代码语言:javascript
复制
 menu.show(field, field.getX(), field.getY()+field.getHeight());
 menu.setVisible(true);
 field.requestFocus();
票数 2
EN

Stack Overflow用户

发布于 2012-08-10 12:39:07

您可以看看JXSearchField,它是新灵的一部分

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10029846

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档