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

Ser*_*kyy 5 java swing popup

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

这是我的代码:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在窗口右边框附近右键单击,我得到一个不可聚焦的文本字段。我在弹出窗口中允许键控制的任何其他组件(例如 JTable)中遇到了同样的问题。

如何在 HeavyWeightPopup 中聚焦组件?

cam*_*ckr 4

几年前我也曾为此苦苦挣扎。我不知道如何将初始焦点放在弹出窗口上的组件上。以下是我的一些问题/观察:

Popup 类是用来做什么的?

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

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

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

使用 JWindow 似乎提供与 Popup 相同的功能。

JPopupMenu 似乎支持上述两个要求。

运行以下程序:

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

在我看来,每当您需要“弹出窗口”时,您都应该使用JPopupMenu.

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();
            }
        });
*/
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:

根据 Sergiy 的回答,这段代码已经接近工作了。该方法的不同之处popupPopup()在于,show()需要在窗口变得可聚焦之后调用该方法。更新了代码以反映此更改。