Java Swing : Controlling focus with textfield and autocompletion dialog/menu

标签 java swing autocomplete jtextfield jdialog

我有一个 JTextField,我正在尝试向其中添加自动完成菜单。但我对如何处理焦点有疑问。

这是一个SSCCE

package test;

import java.awt.Point;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

public class SSCCE extends JFrame implements DocumentListener {
    private AutocompletionDialog dialog;

    public SSCCE() {
        dialog = new AutocompletionDialog ();

        JTextField textField = new JTextField(20);
        textField.getDocument().addDocumentListener(this);

        add(textField);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        pack();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new SSCCE().setVisible(true);
            }
        });
    }

    public void insertUpdate(DocumentEvent e) {
        Point p = this.getLocationOnScreen();
        dialog.setLocation(p.x, p.y + 50);
        dialog.setVisible(true);
    }

    public void removeUpdate(DocumentEvent e) { }
    public void changedUpdate(DocumentEvent e) { }

    private class AutocompletionDialog extends JDialog {
        JList<String> list = new JList<>(
                new String[] { "One", "Two", "Three" });

        AutocompletionDialog() {
            setSize(100, 100);
            add(list);
        }
    }
}

当然,实际程序中有更多逻辑,但我遇到的问题是我想显示自动完成对话框/菜单,但仍然能够继续在文本字段中输入内容。同时,我还希望能够使用向上/向下箭头和 Enter 键以及鼠标导航菜单,以选择完成选项之一。

有人可以帮我解决这里应该如何进行吗?谢谢!

编辑:

感谢@camickr我使用 setFocusableWindowState 和 InputMap/ActionMap 进行了一些尝试,以始终将焦点保持在文本字段中,并手动控制选定的列表项。问题是,与列表具有适当焦点的情况相比,这样做时您会得到视觉上的差异。请参阅屏幕截图。

如果我不扰乱焦点,这就是它的样子(这就是我想要的)。

dialog with proper focus

这就是我运行 setFocusableWindowState(false)

的样子

dialog with no focus

主要区别是所选列表项周围的突出显示边框(深蓝色),以及整个对话框周围的蓝色突出显示。然后标题栏也存在差异。

(不要介意渲染伪影,我正在使用旧的 NX 客户端连接到三年前的虚拟 Linux 安装)

编辑2:

我担心外观或操作系统决定了所选列表项的外观(例如突出显示的边框)。但事实证明,确实只是单元格渲染器进行了该调用。知道编写自己的单元格渲染器让我感觉好多了,现在我有了一个令我满意的解决方案。

这是我最终使用的代码:

private class CellRenderer extends DefaultListCellRenderer
{
    @Override
    public Component getListCellRendererComponent(
            JList<?> jlist, Object value, int index,
            boolean isSelected, boolean cellHasFocus) {
        super.getListCellRendererComponent(
                jlist, value, index, isSelected, cellHasFocus);

        if (isSelected) {
            Border border = UIManager.getBorder(
                    "List.focusSelectedCellHighlightBorder");

            if (border == null) {
                border = UIManager.getBorder(
                        "List.focusCellHighlightBorder");
            }

            setBorder(border);
        }

        return this;
    }
}

最佳答案

As I show the auto completion menu the focus is given to that dialog.

要防止焦点转到弹出窗口,您可以使用:

JDialog dialog = new JDialog(...);
dialog.setFocusableWindowState( false );
...
dialog.setVisible( true );

I also want to be able to navigate the menu with the up/down arrows and the enter key

然后您需要覆盖文本字段提供的默认操作。查看Key Bindings了解更多信息。

您还可以查看:button highlighting using keyboard keys我只是提供了一个实现操作的简单示例。

关于Java Swing : Controlling focus with textfield and autocompletion dialog/menu,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27582212/

相关文章:

java - JAVA 中的机器人 KeyEvent.VK_AT 问题

javascript - Angularjs - 中止/取消运行 $http 调用

ios - 结构初始值设定项不显示?

java - 为类使用 static int 来识别对象对于 OO 来说是一个好的实践吗?

java - 可滚动的新 GuiBuilder 代号一

java - 为什么 Thread 不是抽象类而 start() 不是 final?

autocomplete - 在 Sublime Text 2 上修改 HTML &lt;script&gt; 自动完成

java数组传递,我到处都得到最后一个数组

java - 将值从一个 JtextField 传递到另一个 JtextField?

java - 在 JTextpane 中切换文本换行