首页 > 解决方案 > JPopupMenu 将初始焦点放在子框架 (JTextField) 上,即使超出父框架的边界(重量级)

问题描述

我有这种情况,尽管当弹出菜单超出父框架的边界时调用,但JTextField内部 aJPopupMenu没有获得焦点。requestFocus这在 Linux/Gtk 上具有不同的外观和感觉(例如 Metal)(不确定它与平台有关)。例子:

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class FocusTest implements Runnable {
    public static void main(String[] args) {
        EventQueue.invokeLater(new FocusTest());
    }

    public void run() {
        final JFrame f = new JFrame();
        final JButton invoker = new JButton("Pop");
        final JPopupMenu pop = new JPopupMenu();
        final JTextField text = new JTextField(12);
        pop.add(text);
        pop.pack();
        invoker.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                pop.show(invoker, 0, 0);
                System.out.println("here");
                text.requestFocus();
            }
        });
        f.getContentPane().add(invoker);
        f.pack();
        f.setVisible(true);
    }
}

使用默认帧大小,弹出比帧大,不给焦点:

在此处输入图像描述

当窗口变大时,打开弹出窗口会给出初始焦点,我可以在没有鼠标交互的情况下开始在文本字段中输入:

在此处输入图像描述

这似乎与在第一种情况下弹出窗口是重量级的,而在第二种情况下它是轻量级的事实有关。例如,如果我添加pop.setLightWeightPopupEnabled(false);,则即使弹出窗口包含在父框架内,也不会给出焦点。

我如何确保在任何情况下都给予关注(也适用于重量级同行)?

标签: javaswingpopupfocus

解决方案


因此,明确地使用未装饰的对话框似乎有效:

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JTextField;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class FocusTest implements Runnable {
    public static void main(String[] args) {
        EventQueue.invokeLater(new FocusTest());
    }

    public void run() {
        final JFrame f = new JFrame();
        final JButton invoker = new JButton("Pop");
        final JDialog pop = new JDialog();
        pop.setUndecorated(true);
        final JTextField text = new JTextField(12);
        pop.add(text);
        pop.pack();
        invoker.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                pop.setLocationRelativeTo(invoker);
                pop.setVisible(true);
            }
        });
        f.getContentPane().add(invoker);
        f.pack();
        f.setVisible(true);
    }
}

推荐阅读