java - Swing 持久弹出窗口

标签 java swing mouseevent jpopupmenu jpopup

我需要用我的自定义组件显示一个 swing 弹出窗口。弹出窗口应保持可见,直到我自己将其隐藏,但不应获得焦点。

我有一段由其他开发人员编写的代码,它是通过以下方式实现的:

       popupMenu = new JPopupMenu();
       popupMenu.add(myCustomComponent, BorderLayout.CENTER);
       popupMenu.setFocusable(false);
       popupMenu.setVisible(true);
       popupMenu.show(parentComponent, x, y);

这似乎可行,但有一个错误 - 当弹出窗口可见时,弹出窗口会占用组件外的第一次鼠标单击。所以我需要点击两次才能将焦点设置到另一个组件。

我该如何解决?或者制作弹出窗口的正确方法是什么?

更新

最后,我设法在简短的代码片段中重现了我的问题。感谢 Guillaume Polet 给我一个起点。

代码如下:

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

import javax.swing.*;

public class TestJPopup {

    protected void initUI() {
        JFrame frame = new JFrame(TestJPopup.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JTextField textField = new JTextField("Some text field");
        frame.add(textField, BorderLayout.WEST);
        final JButton buttonToHit = new JButton("Hit me");
        buttonToHit.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(buttonToHit, "You hit the button successfully");
            }
        });
        frame.add(buttonToHit);
        frame.setSize(200, 100);
        frame.setVisible(true);

        final JPopupMenu popup = new JPopupMenu();
        popup.add(new JLabel("<html>Hey!<br>I'm the popup window!</html>"),
                BorderLayout.NORTH);
        popup.setFocusable(false);
        popup.setVisible(true);
        popup.show(textField, 60, 60);

        // I want to activate popup when user clicks in the text field
        textField.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (popup != null) {
                    popup.show(textField, 60, 60);
                }
            }
        });
    }

    public static void main(String[] args) throws Exception {
        Class lnfClass = Class.forName("com.sun.java.swing.plaf.windows.WindowsLookAndFeel", true,
                Thread.currentThread().getContextClassLoader());
        LookAndFeel feel = (LookAndFeel) lnfClass.newInstance();
        UIManager.setLookAndFeel(feel);

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new TestJPopup().initUI();
            }
        });
    }
}

两个关键时刻:

  • 使用 Windows 外观(默认不可重现)
  • 附加到主框架中文本字段的鼠标监听器

最佳答案

不是答案,只是一个例子SSCCE我目前无法在其中重现您描述的行为。也许从这段代码开始,尝试重现错误并使用修改后的非工作代码编辑您的帖子。

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class TestJPopup {

    protected void initUI() {
        JFrame frame = new JFrame(TestJPopup.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JLabel leftLabel = new JLabel("Left");
        frame.add(leftLabel, BorderLayout.WEST);
        final JButton buttonToHit = new JButton("Hit me");
        buttonToHit.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(buttonToHit, "You hit the button successfully");
            }
        });
        frame.add(buttonToHit);
        frame.setSize(500, 400);
        frame.setVisible(true);
        JPopupMenu popupMenu = new JPopupMenu();
        popupMenu.add(new JLabel("<html>A Custom<br>component<br>made to<br> simulate <br>your custom component</html>"),
                BorderLayout.NORTH);
        JTextField textfield = new JTextField(30);
        popupMenu.add(textfield);
        popupMenu.setFocusable(false);
        popupMenu.setVisible(true);
        popupMenu.show(leftLabel, 20, 20);
        // Let's force the focus to be in a component in the popupMenu
        textfield.requestFocusInWindow();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestJPopup().initUI();
            }
        });
    }
}

关于java - Swing 持久弹出窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12606675/

相关文章:

java - 使用java将PDF转图像

java - 如何为我的 java swing 应用程序准备 Mac 安装程序

java - 从表模型中删除行后恢复 jTable 焦点和位置

java - BouncycaSTLe 签名数据消息中的附加八位字节字符串

java - Retrofit 2 中同步请求和异步请求哪个更好

java - 如何在特殊的抽象模型JTable中使列可编辑

javascript - Canvas 上的圆和线

macos - 自定义 NSStatusItem 和 NSView 无法可靠地接收 NSTrackingEvents

vb.net - 在 PictureBox 上绘制矩形

java - 得墨忒耳法则——只用一个点,我能改进这个逻辑吗?