Java JTextField在重量级弹出窗口中没有焦点

Java JTextField在重量级弹出窗口中没有焦点,java,swing,popup,Java,Swing,Popup,我想在弹出窗口中显示一个文本文件。当弹出窗口完全覆盖在应用程序框架上时(MediumWeightPopup)-一切正常,但当弹出窗口的一部分位于框架外时(HeavweightPopup),它无法聚焦。在这种情况下,插入符号是不可见的,无法输入文本 这是我的密码: import java.awt.BorderLayout; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swin

我想在弹出窗口中显示一个文本文件。当弹出窗口完全覆盖在应用程序框架上时(MediumWeightPopup)-一切正常,但当弹出窗口的一部分位于框架外时(HeavweightPopup),它无法聚焦。在这种情况下,插入符号是不可见的,无法输入文本

这是我的密码:

import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class PopupTest {

    public static void main(String[] args) {
        JFrame frm = new JFrame("Popup test");
        JPanel p = new JPanel();
        p.addMouseListener(new MouseAdapter() {
            Popup pop;
            @Override
            public void mouseReleased(MouseEvent e) {
                if (SwingUtilities.isRightMouseButton(e)) {
                    if (pop != null) {
                        pop.hide();
                    }
                    JPanel popupPanel = new JPanel(new BorderLayout());
                    JTextField field = new JTextField(20);
                    popupPanel.add(field);
                    pop = PopupFactory.getSharedInstance().getPopup(p, popupPanel, e.getXOnScreen(), e.getYOnScreen());
                    pop.show();
                    System.out.println("Popup type: " + pop.getClass().getName());
                    System.out.println("Can get focus? " + field.requestFocusInWindow());
                }
            }
        });
        frm.add(p);
        frm.setSize(500, 300);
        frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frm.setLocationRelativeTo(null);
        frm.setVisible(true);
    }
}
在窗口右边框附近单击鼠标右键,我得到一个不可聚焦的文本字段。弹出窗口中允许键控制的任何其他组件(例如JTable)也存在同样的问题


如何在重量级人物中聚焦某个组件?

几年前我也在努力解决这个问题。我不知道如何在弹出窗口中为组件提供初始焦点。以下是我的一些问题/意见:

弹出类的用途是什么

我一直认为弹出窗口应该具有一些基本功能,例如在以下情况下,弹出窗口应该关闭:

a) 按下退出键 b) 弹出窗口失去焦点

popup类不提供上述任何功能,实际上似乎需要一些模糊的代码才能使键盘焦点正常工作

使用JWindow似乎提供了与弹出窗口相同的功能

JPOppMenu似乎支持上述两种需求

运行以下程序:

a) 单击每个按钮 b) 单击框架的空白部分

在我看来,无论何时需要“弹出窗口”,都应该使用
jpopmpmenu

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;

public class PopupTest extends JFrame
{
    String[] numbers = { "one", "two", "three", "four", "five" };

    public PopupTest()
    {
        getContentPane().setLayout( new FlowLayout() );
        getContentPane().setBackground(Color.YELLOW);

        JButton popup = new JButton("Popup as Popup");
        popup.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                popupPopup(e);
            }
        });
        getContentPane().add(popup);
        JButton window = new JButton("Window as Popup");
        window.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                windowPopup(e);
            }
        });
        getContentPane().add(window);

        JButton menu = new JButton("PopupMenu as Popup");
        menu.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                menuPopup(e);
            }
        });
        getContentPane().add(menu);
    }

    private void popupPopup(ActionEvent e)
    {
        JList list = new JList(numbers);
        list.setSelectedIndex(0);

        PopupFactory factory = PopupFactory.getSharedInstance();
        Popup popup = factory.getPopup(this, list, getLocation().x, getLocation().y+100);
        //popup.show();

        Window window = SwingUtilities.windowForComponent(list);

        if (window != null)
        {
            window.setFocusableWindowState(true);
        }

        popup.show();
        KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent(list);
    }

    private void windowPopup(ActionEvent e)
    {
        JList list = new JList(numbers);
        list.setSelectedIndex(0);

        JWindow window = new JWindow(this);
        window.getContentPane().add(list);
        window.pack();
        window.setVisible(true);
        window.setLocation(getLocation().x + 200, getLocation().y+100);

        window.addWindowListener( new WindowAdapter()
        {
            public void windowDeactivated(WindowEvent e)
            {
                System.out.println("deactivated");
            }
        });
    }

    private void menuPopup(ActionEvent e)
    {
        JList list = new JList(numbers);
        list.setSelectedIndex(0);

        JPopupMenu menu = new JPopupMenu();
        menu.add( new JTextField(10) );
        menu.add( list );

        menu.show((Component)e.getSource(), 0, 100);
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new PopupTest();
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.setSize(500, 200);
        frame.setLocationRelativeTo( null );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater( () -> createAndShowGUI() );
/*
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
*/
    }
}
编辑:


根据Sergiy的回答,该代码几乎可以正常工作。
popuppop()
方法的区别在于,在使窗口成为焦点后,需要调用
show()
方法。更新代码以反映此更改。

源代码分析为我带来了另一个解决方案

pop = PopupFactory.getSharedInstance().getPopup(p, popupPanel, e.getXOnScreen(), e.getYOnScreen());
// some new stuff
Window win = SwingUtilities.windowForComponent(popupPanel);
if (win instanceof JWindow && win.getType() == Window.Type.POPUP) {
    win.setFocusableWindowState(true);
}
// continue old stuff
pop.show();
因此,完整的示例如下所示

import java.awt.BorderLayout;
import java.awt.Window;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JWindow;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class PopupTest {

    public static void main(String[] args) {
        JFrame frm = new JFrame("Popup test");
        JPanel p = new JPanel();
        p.addMouseListener(new MouseAdapter() {
            Popup pop;
            @Override
            public void mouseReleased(MouseEvent e) {
                if (SwingUtilities.isRightMouseButton(e)) {
                    if (pop != null) {
                        pop.hide();
                    }
                    JPanel popupPanel = new JPanel(new BorderLayout());
                    JTextField field = new JTextField(20);
                    popupPanel.add(field);
                    pop = PopupFactory.getSharedInstance().getPopup(p, popupPanel, e.getXOnScreen(), e.getYOnScreen());
                    Window win = SwingUtilities.windowForComponent(popupPanel);
                    if (win instanceof JWindow && win.getType() == Window.Type.POPUP) {
                        win.setFocusableWindowState(true);
                    }
                    pop.show();
                    System.out.println("Popup type: " + pop.getClass().getName());
                    System.out.println("Can get focus? " + field.requestFocusInWindow());
                }
            }
        });
        frm.add(p);
        frm.setSize(500, 300);
        frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frm.setLocationRelativeTo(null);
        frm.setVisible(true);
    }
}
有趣的:调用
字段。requestFocusInWindow()
仍然返回false,但字段仍然获得焦点


BTW:这个解决方案对我来说也更好,因为在我的真实代码中,我从一个
JComboBox
中获得弹出窗口(我的目标是创建
JTableComboBox
,弹出窗口中有一个表格,表格顶部有一个可选的过滤器字段)。

感谢这个解决方案(我的upvote+标记为已接受)。也许我会在别的地方用。但是我找到了另一个,在我的情况下更好。你能解释一下为什么Window.setFocusableWindowsState(true)解决了这个问题吗?如果在将GetFocusableWindowsState设置为true之前调用它,它也会返回true。不明白为什么。。。