Java MouseListener在运行中期开始给出错误

Java MouseListener在运行中期开始给出错误,java,swing,jpanel,mouselistener,Java,Swing,Jpanel,Mouselistener,我目前正在制作一个游戏,涉及通过JPanel制作的按钮。但是,在程序运行时的某个时刻,每当鼠标事件以以下形式注册时,用于制作按钮的JPanel开始给出恒定错误: at java.awt.AWTEventMultiCaster.mouse[eventName](UnknownSource) 它运行得如此之快,以至于我看不到初始错误,错误只在运行中期的某个点开始。有人能帮我吗?以下是我的JPanel的代码: JPanel trackPanel = new JPanel() { in

我目前正在制作一个游戏,涉及通过JPanel制作的按钮。但是,在程序运行时的某个时刻,每当鼠标事件以以下形式注册时,用于制作按钮的JPanel开始给出恒定错误:

at java.awt.AWTEventMultiCaster.mouse[eventName](UnknownSource)
它运行得如此之快,以至于我看不到初始错误,错误只在运行中期的某个点开始。有人能帮我吗?以下是我的JPanel的代码:

JPanel trackPanel = new JPanel() {
        int state = 0;
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponents(g);

            addMouseListener(new MouseAdapter() {
                public void mouseEntered(MouseEvent e) {
                    if (dragMe == null) {
                        state = 1;
                    }
                }
                public void mouseExited(MouseEvent e) {
                    if (dragMe == null) state = 0;
                    else state = 1;
                }
                public void mousePressed(MouseEvent e) {
                    if (dragMe == null && !e.isMetaDown())
                    {
                        dragMe = new DragFrameThread(vTrack);
                        dragMe.start();
                    }
                    state = 2;
                }
                public void mouseReleased(MouseEvent e) {
                    if (state == 2 && e.isMetaDown()) System.exit(0);
                    if (dragMe != null) {
                        dragMe.interrupt();
                        dragMe = null;
                        state = 1;
                    }
                }
            });

            g.setColor(new Color(0, 127, 127, 255));
            g.drawRect(0, 0, getWidth()-1, getHeight()-1);
            g.setColor(new Color(0, 127, 127, 223));
            g.drawRect(1, 1, getWidth()-3, getHeight()-3);
            g.setColor(new Color(0, 127, 127, 191));
            g.drawRect(2, 2, getWidth()-5, getHeight()-5);
            g.setColor(new Color(0, 127, 127, 159));
            g.fillRect(3, 3, getWidth()-6, getHeight()-6);

            g.drawImage(BootAssets.VTScaledLogo, 0, 0, getWidth(), getHeight(), null);

            if (state == 1) g.setColor(new Color(255, 255, 255, 127));
            if (state == 2) g.setColor(new Color(0, 0, 0, 127));
            if (state != 0) g.fillRect(0, 0, getWidth(), getHeight());

            repaint();
        }
    };
非常感谢!
~Para

我认为问题在于在绘制小部件时调用了
paintComponent
方法。在每次绘制调用中添加鼠标侦听器是错误的

将addMouseListener移出paintComponent方法,并将其单独添加到轨迹面板。您将需要重构代码,因为它当前已设置状态,并以定义JPanel的方式进行更新

       private final AtomicInteger state = new AtomicInteger(0);
       JPanel trackPanel = new JPanel() {
        @Override
        protected void paintComponent(Graphics g)
        {
            super.paintComponent(g);

            g.setColor(new Color(0, 127, 127, 255));
            g.drawRect(0, 0, getWidth()-1, getHeight()-1);
            g.setColor(new Color(0, 127, 127, 223));
            g.drawRect(1, 1, getWidth()-3, getHeight()-3);
            g.setColor(new Color(0, 127, 127, 191));
            g.drawRect(2, 2, getWidth()-5, getHeight()-5);
            g.setColor(new Color(0, 127, 127, 159));
            g.fillRect(3, 3, getWidth()-6, getHeight()-6);

            g.drawImage(BootAssets.VTScaledLogo, 0, 0, getWidth(), getHeight(), null);

            if (state.get() == 1) g.setColor(new Color(255, 255, 255, 127));
            if (state.get() == 2) g.setColor(new Color(0, 0, 0, 127));
            if (state.get() != 0) g.fillRect(0, 0, getWidth(), getHeight());                
        }
    };

    trackPanel.addMouseListener(new MouseAdapter() {
        public void mouseEntered(MouseEvent e) {
            if (dragMe == null) {
                state.set(1);
            }
        }
        public void mouseExited(MouseEvent e) {
            if (dragMe == null) state.set(0);
            else state.set(1);
        }
        public void mousePressed(MouseEvent e) {
            if (dragMe == null && !e.isMetaDown())
            {
                dragMe = new DragFrameThread(vTrack);
                dragMe.start();
            }
            state.set(2);
        }
        public void mouseReleased(MouseEvent e) {
            if (state.get() == 2 && e.isMetaDown()) System.exit(0);
            if (dragMe != null) {
                dragMe.interrupt();
                dragMe = null;
                state.set(1);
            }
        }
    });

我可能没有遵循这里的代码,但是每次调用paintComponet时,它似乎都在注册一个新的侦听器。监听器不应该被添加到轨迹面板上一次,而不是在每次绘制调用中吗?这看起来是正确的答案@KevinO@KevinO嗯,问题是除了paintComponent之外,我似乎无法在任何位置添加侦听器。@UnityParadox,我将假定无法移动侦听器的理由是因为状态变量是在JPanel中定义的。请参阅我的答案以获得建议,但示例代码中的方法不是很好的OO设计。我会考虑使用子面板JPAND,谢谢您的帮助!然而,在您最初的回复之后,我发现了一个不同的解决方案,在JPanel的代码中生成一个私有布尔值,并测试它是否为真,如果不是,则添加侦听器并将其设置为真。您提供的解决方案会更有效吗?@UnityParadox,答案中的解决方案会稍微更有效,因为您不会每次都检查是否需要添加侦听器。添加监听器后,不会使绘制回调变得杂乱无章,这也是更简洁的代码。添加侦听器是一个令人困惑的地方。可读性和可维护性也是重要的考虑因素,而不仅仅是使代码正常工作。当您需要重构某些东西时会发生什么?油漆方法只能处理油漆。让方法做它设计要做的一件事。将鼠标侦听器添加到paint回调外部的面板。感谢您的帮助!我稍后会检查这个,因为我现在不能。