如何从 Mouseevents 中隐藏 JComponent 的一部分?例如。 JButton 的某些区域没有反应,休息很好

How can part of JComponent be obscured from Mouseevents? E.g. some region of JButton not reacting, rest is fine

这个问题花了我很多时间来确定,现在我很好奇是什么导致了这种奇怪的行为:

在示例中,有一个 JFrame class,它显示一个 JPanel“页面”,它本身获取对“父”JFrame 的引用。 我的错误是在构建对象的过程中这样做了。

令人惊叹的是,在某些情况下,JComponents 在“页面”上的反应(如 JButtons、JRadioButtons、JCHeckboxes 等),有时对鼠标的反应很好,有时则完全没有,并且有时只有一小部分表面在工作。

所以我尝试在下面的最小示例中将其隔离,我可以在 Windows 7 x64 和 Windows 10 x64 上的 JRE 1.8、JRE12 和 JRE13 上进行演示。

为了重现,您可能需要调整按钮大小与 JFrame.setSize()。 在我的系统上,按钮对鼠标的反应非常好,mouseEntered 上有一些动画,用鼠标单击会触发 ActionEvent但不在按钮右下角的固定大小区域。如果你用鼠标去那里,不会触发任何事件。 在 windows 大小和组件大小的变化下,该“死”区域的大小保持不变,因为您可以在“页面”代码中尝试使用不同的 LayoutManagers

这同样适用于触发事件的其他 JComponents。

我的问题是:为什么ActionListening-System有问题。如果 Listening 要么完全被破坏,要么根本没有,这将是直观的。

希望从回答中了解更多关于JComponents中鼠标事件生成的内幕,以便在以后的程序中更加警惕。

这是主要的 JFFrame:

import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class TESTFRAME extends JFrame {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TESTFRAME();
            }
        });
    }

    public TESTFRAME() {
        super("TESTFRAME");
        PAGE page = new PAGE();
        /*
         * the following line causes very strange behaviour!
         */
        page.setParent(this);

    
        JPanel DISPLAY = new JPanel(new BorderLayout());
        DISPLAY.add(page);
        add(DISPLAY);
        setSize(800, 600);
        setLocationByPlatform(true);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setVisible(true);
    }
}

仅供参考,还检查注释掉行 page.setParent(this);.

时会发生什么

这是要在框架中显示的“页面”:

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

import javax.swing.JButton;
import javax.swing.JPanel;

public class PAGE extends JPanel implements ActionListener {

    public TESTFRAME parent = null;

    public PAGE() {
        // !!! activate the following line setting the GridLayout, to make button large
        // in the bottom right corners, I continue not being able to click
        // setLayout(new GridLayout(1, 0));

        JButton bt_large = new JButton("<html><br>large close button<br><br></html>");
        bt_large.addActionListener(this);
        add(bt_large);

        JButton bt_small = new JButton("small button");
        bt_small.addActionListener(this);
        add(bt_small);
    }

    public TESTFRAME getParent() {
        return parent;
    }

    public void setParent(TESTFRAME parent) {
        this.parent = parent;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("button click received!");
        if (parent != null) {
            parent.dispose();
        }
    }
}

感谢您的见解!

问题是getParent()Componentclass的一个方法。

通过实施您自己的方法,默认功能会丢失,从而导致您遇到问题。

尝试将您的方法重命名为 getParentFrame()setParentFrame() 以查看正常行为。

但是,您甚至不需要那些方法。相反,您可以使用 JDK.

中的方法访问面板的父框架

在您的 ActionListener 中,您可以使用如下代码:

Window window = SwingUtilities.windowForComponent( this );
window.dispose();