【问题标题】:How to mimic the behavior of JPopupMenu with JDialog?如何用 JDialog 模仿 JPopupMenu 的行为?
【发布时间】:2022-01-23 05:34:59
【问题描述】:

我正在使用 Swing 实现“应用内”搜索引擎,我希望它的行为与 Windows 10 的搜索框完全相同。

搜索框应该:

  • 在搜索按钮的上方和右侧打开,触摸按钮的边缘。
  • 打开时有焦点。
  • 按下搜索按钮即可关闭(如果打开)。
  • 在搜索框外的任意位置用鼠标按下时关闭(如果打开)。

如果 JPopUpMenu 可以将 JDialog 作为它的子级,那就太完美了,但是因为我不需要从头开始实现这些行为(或者我需要吗?)。

这是我第一次使用 Swing,我很难自己实现所有内容。
我尝试在网上寻找示例,但找不到太多有用的信息。

对于 JPopUpMenu 无法托管 JDialog,是否有解决方法?
是否有实施我描述的行为的示例?

谢谢

================================编辑=============== ============== 感谢到目前为止的cmets。除了一个问题之外,我已经设法获得了我想要的行为。

以下代码创建一个带有按钮的框架:

public static void main(String[] args){
    
    JFrame mainWindow = new JFrame();
    mainWindow.setSize(420,420);
    mainWindow.setVisible(true);

    JFrame popUp = new JFrame();
    popUp.setSize(210, 210);

    JButton button = new JButton("button");
    mainWindow.add(button);

    button.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            if(!button.isSelected()){
                button.setSelected(true);
                popUp.setVisible(true);
            }
            else{
                button.setSelected(false);
                popUp.setVisible(false);
            }
        }
    });

    popUp.addWindowFocusListener(new WindowAdapter() {
        @Override
        public void windowLostFocus(WindowEvent e) {
            popUp.setVisible(false);
        }
    });
}

当我点击按钮时,会出现一个弹出窗口,如果我点击主窗口外,弹出窗口会消失,但是当我想重新打开弹出窗口时,我需要按两次按钮。

当弹出窗口因失去焦点而关闭时,如何让按钮正常操作?

【问题讨论】:

  • 您不能将 JDialog 添加到任何内容,因为它与操作系统本机对等窗口相关联。您可能想考虑使用 JWindow 来完成您想要完成的工作
  • 不确定您的问题是什么。您可以轻松地使用所需的任何组件创建 JDialog。您向按钮添加逻辑以检查对话框是否可见,然后进行适当的处​​理。您将对话框设置为非模态对话框,以便在对话框可见时将焦点集中到对话框上的任何组件。您可以将 WindowListener 添加到对话框并处理 windowDeactivated 事件以关闭对话框。如果您需要更多帮助,请发帖 minimal reproducible example 展示您所做的工作,并一次提出一个具体问题。
  • 如果您想要 JDialogue 行为然后使用 JDialogue 并将其简单地定位在屏幕上 relative to your menu,或者如果您可以使用 yourPopup.insert(component, index); 将按钮或类似内容插入到您的 JPopupMenu 中并让按钮执行相关行动。

标签: java swing


【解决方案1】:

您的“解决方案”非常脆弱。在左键单击JButton 之前尝试移动主JFrame

Oracle 有一个有用的教程,Creating a GUI With Swing。跳过 Netbeans 部分。学习本教程的其余部分。

我创建了一个主要的JFrame,它会弹出一个JDialog。我把关闭的JButton 放在JDialog 上。 JDialog 是模态的,这意味着当 JDialog 可见时,您无法访问主 JFrame

您可以将JDialog 放置在屏幕上您希望的任何位置。通常,您有一个JDialog 出现在父JFrame 的中心。这就是用户期望出现对话框的地方。我将JDialog 放在左上角,只是为了向您展示它是如何完成的。

这是完整的可运行代码。

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

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class PopupExample {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new PopupExample().createAndShowGUI());
    }

    private JFrame mainWindow;

    public void createAndShowGUI() {
        mainWindow = new JFrame("Main Window");
        mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        mainWindow.add(createMainPanel(), BorderLayout.CENTER);

        mainWindow.pack();
        mainWindow.setLocationByPlatform(true);
        mainWindow.setVisible(true);
    }

    private JPanel createMainPanel() {
        JPanel panel = new JPanel(new FlowLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(200, 200, 200, 200));

        JButton button = new JButton("button");
        panel.add(button);

        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                createAndShowDialog(mainWindow);
            }
        });

        return panel;
    }

    private void createAndShowDialog(JFrame frame) {
        JDialog dialog = new JDialog(frame, "Dialog", true);
        dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        dialog.add(createDialogPanel(dialog), BorderLayout.CENTER);

        dialog.pack();
        
        // Here's where you set the location of the JDialog relative
        // to the main JFrame
        Point origin = frame.getLocation();
        dialog.setLocation(new Point(origin.x + 30, origin.y + 30));
        
        dialog.setVisible(true);
    }

    private JPanel createDialogPanel(JDialog dialog) {
        JPanel panel = new JPanel(new FlowLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(100, 100, 100, 100));

        JButton button = new JButton("Close");
        panel.add(button);

        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                dialog.dispose();
            }
        });

        return panel;
    }

}

【讨论】:

  • 感谢您的回答,但我觉得我的问题没有被理解。我的问题(编辑后)是“如何创建一个在按下按钮时打开和关闭并在失去焦点时关闭的 JFrame?”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-28
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多