【问题标题】:Problems with swing components and awt eventsswing组件和awt事件的问题
【发布时间】:2010-11-13 20:27:42
【问题描述】:

我的 java gui 代码似乎有问题,我不知道为什么它不起作用。

需要发生的是当鼠标点击面板或框架 - 现在让我们说面板;因为这只是一个测试,最终此代码将为另一个 gui 组件实现,但我想先让它工作 - 弹出菜单需要变得可见并且需要焦点在文本字段上设置。然后当用户按下回车键或文本字段上的焦点丢失时,弹出菜单需要隐藏,文本重置为空白或我需要的任何内容。

这就是我写的:

public class Test {
    private final JFrame frame = new JFrame();
    private final JPanel panel = new JPanel();
    private final JPopupMenu menu = new JPopupMenu();
    private final JTextField field = new JTextField();
    private final Obj obj;

    //... constructor goes here

    public void test(){
        frame.setSize(new Dimension(200,200));
        field.setColumns(10);
        field.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent arg0) {
                obj.method(field.getText());
                menu.setVisible(false);
                field.setText("");
            }
        });
        field.addFocusListener(new FocusListener() {
             public void focusLost(FocusEvent e) {
                 menu.setVisible(false);
                 field.setText("");
             }

             //... focus gained event goes here
        });
        panel.addMouseListener(new MouseListener() {
            public void mouseClicked(MouseEvent e) {
                menu.setLocation(e.getX(), e.getY());
                menu.setVisible(true);
                field.requestFocusInWindow();
            }

            //... other mouse events go here
        });

        menu.add(field);
        frame.getContentPane().add(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

使用此处编写的代码,菜单会在我单击后立即自动隐藏。它只是在屏幕上短暂闪烁,然后在我不做任何其他事情的情况下隐藏。

如果我更改代码以排除任何出现的menu.setVisible(false),那么文本字段将永远不会获得焦点。

这是因为误用了 JPopupMenu 吗?我哪里错了?

还请注意,我遗漏了 main 或 Obj。它们在另一个文件中,很可能对这个问题无关紧要。 Obj.method() 什么都不做,main 只调用 Test 的构造函数和 test() 方法。

【问题讨论】:

  • 弹出菜单的作用是什么?
  • 对我来说似乎很奇怪,您在弹出菜单中有一个文本字段。这种方法背后的动机是什么?也许还有另一种方法可以做到这一点......

标签: java user-interface swing events awt


【解决方案1】:

这段代码应该按照你想要的方式工作(希望你遵循匿名类的使用:

public class Test {

public static void main(String[] args) {
    Test test = new Test();
    test.test();
}

private JFrame frame;
private JPanel panel;
private JPopupMenu menu;
private JTextField field;

public Test() {
    frame = new JFrame();
    frame.setSize(new Dimension(200, 200));
    frame.getContentPane().add(getPanel());
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

private JPanel getPanel() {
    if (panel == null) {
        panel = new JPanel();
        panel.setComponentPopupMenu(getMenu());
        panel.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                menu.show(panel, e.getX(), e.getY());
            }
        });
    }
    return panel;
}

private JPopupMenu getMenu() {
    if (menu == null) {
        menu = new JPopupMenu() {

            @Override
            public void setVisible(boolean visible) {
                super.setVisible(visible);
                if (visible) {
                    getField().requestFocus();
                }
            }
        };
        menu.add(getField());
    }
    return menu;
}

private JTextField getField() {
    if (field == null) {
        field = new JTextField();
        field.setColumns(10);
        field.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                getMenu().setVisible(false);
            }
        });
    }
    return field;
}

public void test() {
    frame.setVisible(true);
}
}

要注意的关键是我们在设置弹出菜单时:

panel.setComponentPopupMenu(getMenu());
panel.addMouseListener(new MouseAdapter() {
    @Override
    public void mouseClicked(MouseEvent event) {
        getMenu().show(getPanel(), event.getX(), event.getY());
    }
});

以及当弹出菜单可见时如何为文本字段请求焦点,这是通过请求焦点的文本字段完成的,而不是窗口中的焦点,因为它不存在于窗口中,仅在菜单中:

menu = new JPopupMenu() {
    @Override
    public void setVisible(boolean visible) {
        super.setVisible(visible);
        if (visible) {
            getField().requestFocus();
        }
    }
};

最后是文本字段如何关闭弹出菜单:

field.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        getMenu().setVisible(false);
    }
});

【讨论】:

    【解决方案2】:

    您应该能够通过覆盖 getComponentPopupMenu 以返回 JPopupMenu 来做到这一点。这应该完全按照您的意愿处理。它将允许焦点等。

    编辑:这不是绝对必要的,尽管它确实允许更好的继承。

    Public JPopupMenu getComponentPopupMenu() {
        return getMenu();
    }
    

    哦,如果您希望它在任何鼠标单击时显示,请添加鼠标侦听器,然后在弹出菜单上调用 show:

    public void processMouseEvent(MouseEvent e) {
        popup.show(this, e.getX(), e.getY());
    }
    

    这将在任何鼠标点击时显示。

    或者,如果您有一个鼠标监听器(调用 processMouseEvent)并且您只想在右键单击时调用:

    public void processMouseEvent(MouseEvent e) {
        if (e.isPopupTrigger()) {
            popup.show(this, e.getX(), e.getY());
        }
    }
    

    鼠标监听器看起来像这样:

    panel.addMouseListener(new MouseAdapter() {
        mouseClicked(MouseEvent e) {
            processMouseEvent(e);
        }
    }
    

    【讨论】:

    • 我将更新我的问题,但我所做的只是将 setVisible 更改为显示并且它可以工作,只是焦点不会自动转移到文本字段。它不再隐藏...谢谢。
    • 对,如果您使用 getPopupMenu 或执行 popup.show(...) 焦点将由 Swing 处理,您可以免费获得该行为。
    • 我添加了一些片段来尝试使这一点更加清晰 - 鼠标侦听器调用 mouseEvent 方法。同样,通过 popup.show,您可以让底层框架为您处理焦点。
    • 我真的不明白该放在哪里,我要覆盖谁的 getComponentPopupMenu?
    • 抱歉 - getComponentPopupMenu 是在 Swing 中向组件添加弹出菜单的“标准”或“首选”方式。您覆盖您想要弹出菜单的组件,并让它返回您的菜单。然后,您有一个鼠标侦听器,其代码类似于处理鼠标事件,它调用类似 getComponentPopupMenu().show(this, e.getX(), e.getY())
    【解决方案3】:

    我想指出,通过使用建议的方法,我发现setComponentPopupMenu() 会自动添加一个 MouseListener 来显示给定的 PopupMenu,然后使用右键单击事件。
    因此if(e.isPopupTrigger()) 结构中的任何内容都不会在右键单击时运行,因为该事件已被消耗。

    所以基本上我只是通过添加panel.setComponentPopupMenu(getMenu()) 来获得我的问题中指定的行为,但事实上它消耗了我所有的右键单击事件,而不仅仅是 mouseClicked,这是非常有限的。

    【讨论】:

      【解决方案4】:

      当您显示一个弹出窗口时,它应该具有焦点(并且可能会抓住它)其他任何东西实际上都没有多大意义。

      所以可能发生的事情是这样的: 菜单显示,并抓住焦点。

      使用下一个命令,您将焦点移动到文本字段。由于弹窗没有焦点,没有焦点的弹窗也没用,所以又隐藏了。

      【讨论】:

      • 这真的没有意义,因为它只有在我的代码中有 menu.setVisible(false) 时才会隐藏,但即使我有 field.requestFocusInWindow() 它也不会隐藏。
      猜你喜欢
      • 2014-06-14
      • 2011-12-06
      • 1970-01-01
      • 2021-12-07
      • 2013-01-28
      • 1970-01-01
      • 2019-06-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多