繁体   English   中英

秋千组件和awt事件的问题

[英]Problems with swing components and awt events

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

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

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

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

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

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

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

所以可能发生的是:菜单显示并抓住焦点。

使用下一个命令,您可以将焦点移至文本字段。 由于弹出窗口没有焦点,而没有焦点的弹出窗口没有用,因此它将再次隐藏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM