swing组件和awt事件的问题

发布于 2024-07-28 15:34:20 字数 2006 浏览 3 评论 0原文

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

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

这就是我写的:

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() 方法。

I seem to be having problems with my java gui code, and I have no idea why it's not working.

What needs to happen is when the mouse is clicked on the panel or frame - for now lets just say panel; as this is just a test eventually this code will be implemented for another gui component, but I'd like to get this working first - the popup menu needs to become visible and the focus needs to be set on the text field. Then when the user presses enter or the focus on the text field is lost then the popup menu needs to hide and the text reset to blank or whatever I need it to be.

So this is what I wrote:

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);
    }
}

With the code as it is written here the menu automatically hides right after I click. It just flashes on screen briefly and then hides without me doing anything else.

If I change the code to exclude any occurrences of menu.setVisible(false) then the text field will never gain focus.

Is this due to a misuse of JPopupMenu? Where am I going wrong?

Also note that I left out main or Obj. They are in another file and most likely insignificant to this problem. Obj.method() does nothing and main only calls Test's constructor and test() method.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

眼眸印温柔 2024-08-04 15:40:00

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

那么可能发生的情况是这样的:
菜单显示,并抓住焦点。

使用下一个命令,您将焦点移动到文本字段。 由于弹出窗口没有焦点,而没有焦点的弹出窗口是没有用的,所以它会再次隐藏。

When you show a popup it should have the focus (and it probably grabs it) anything else really doesn't make to much sense.

So what's probably happens is this:
the Menu shows, and grabs the focus.

with the next command you travers the focus to the textfield. Since the popup has no focus and a popup without focus is useless, it hides again.

娇妻 2024-08-04 15:39:02

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

因此,本质上,我只需添加 panel.setComponentPopupMenu(getMenu()) 即可获得问题中指定的行为,但事实上,它消耗了我所有的右键单击事件,而不仅仅是 mouseClicked,这是极其有限的。

I'd like to point out that I'm discovering through usage of the suggested methods that setComponentPopupMenu() automatically adds a MouseListener to display the given PopupMenu which then consumes the right-click event.
so whatever is inside the if(e.isPopupTrigger()) structure is never run on right clicks because the event is consumed.

So essentially I get the behavour specified in my question just by adding panel.setComponentPopupMenu(getMenu()), but the fact that it's consuming all my right-click events, not just mouseClicked, is extremely limiting.

草莓味的萝莉 2024-08-04 15:38:09

您应该能够通过重写 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);
    }
}

You should be able to do this by overriding getComponentPopupMenu to return a JPopupMenu. This should handle exactly like you want. It will allow for focus, etc.

EDIT: This is not strictly necessary, although it does allow better for inheritance.

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

Oh, and if you want it to show up on any mouse click, add a mouse listener, and call show on the popupmenu:

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

That will show it on any mouse click.

or, another option is if you have a mouse listener (calling processMouseEvent) and you only want to call on right-click:

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

The mouse listener would look like this:

panel.addMouseListener(new MouseAdapter() {
    mouseClicked(MouseEvent e) {
        processMouseEvent(e);
    }
}
極樂鬼 2024-08-04 15:37:25

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

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);
    }
});

This code should work the way you want it to work (hopefully you follow the use of anonymous classes:

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);
}
}

The key things to notice are when we setup the pop-up menu:

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

And how you request focus for the text field when the pop up menu is visible, which is accomplished through the text field requesting focus, but not focus in window since it doesn't exist in the window, only in the menu:

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

And finally how the text field dismisses the pop up menu:

field.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        getMenu().setVisible(false);
    }
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文