Java JFrame frame.addMouseListener 不工作

Java JFrame frame.addMouseListener doesent work

我目前正在 java 中编写需要接收用户输入的应用程序。我尝试了很多方法来实现输入,但其中 none 行得通。如果有帮助,我正在使用图形界面渲染对象。我尝试了几种方法来实现鼠标交互:

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class Window extends Canvas {
    JFrame frame;
    boolean mousePressed = false;

    public Window(String windowName, int windowWidth, int windowHeight, Main main) {
        frame = new JFrame(windowName);
        frame.setSize(new Dimension(windowWidth, windowHeight));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.addMouseListener(new MouseListener() {
            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("Clicked!");
            }

            @Override
            public void mousePressed(MouseEvent e) {
                System.out.println("Clicked!");
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                System.out.println("Clicked!");
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                System.out.println("Clicked!");
            }

            @Override
            public void mouseExited(MouseEvent e) {
                System.out.println("Clicked!");
            }
        });
        frame.add(main);
        frame.setVisible(true);
        main.start();
    }
}

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class Window extends Canvas implements MouseListener {
    JFrame frame;
    boolean mousePressed = false;

    public Window(String windowName, int windowWidth, int windowHeight, Main main) {
        frame = new JFrame(windowName);
        frame.setSize(new Dimension(windowWidth, windowHeight));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.addMouseListener(this);
        frame.add(main);
        frame.setVisible(true);
        main.start();
    }
            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("Clicked!");
            }

            @Override
            public void mousePressed(MouseEvent e) {
                System.out.println("Clicked!");
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                System.out.println("Clicked!");
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                System.out.println("Clicked!");
            }

            @Override
            public void mouseExited(MouseEvent e) {
                System.out.println("Clicked!");
            }
}

然而,当我 运行 应用程序时,它不会打印任何内容。 这是我的主要 class:

import java.awt.*;
import java.awt.image.BufferStrategy;

public class Main extends Canvas implements Runnable {
    final String windowName = "Hand Written Digits Reader";
    final int windowWidth = 500;
    final int windowHeight = 500;

    boolean running = false;

    Window window;
    Thread thread;
    NeuralNetwork neuralNetwork = new NeuralNetwork();

    public Main() {
        window = new Window(windowName, windowWidth, windowHeight, this);
    }
    public void start() {
        thread = new Thread(this);
        thread.start();
        running = true;
    }
    public void stop() {
        try {
            thread.join();
            running = false;
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    public void run() {
        long lastTime = System.nanoTime();
        double fps = 1.0;
        double ns = 100000000 / fps;
        double delta = 0;

        while(running)
        {
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            lastTime = now;
            while(delta >= 1)
            {
                tick();
                delta--;
            }

            render();
        }
        stop();
    }
    public void tick() {
    }
    public void render() {
        BufferStrategy bs = this.getBufferStrategy();
        if (bs == null) {
            this.createBufferStrategy(3);
            return;
        }
        Graphics g = bs.getDrawGraphics();
        neuralNetwork.drawGUI(g, window.frame, window.mousePressed);

        g.dispose();
        bs.show();
    }
    public static void main(String[] args) {
        new Main();
    }
}

MouseListener 添加到您有兴趣监视的组件,在这种情况下,这将是您的 Main class.

JFrame 永远不是 MouseListener 的好候选者,它是一个复合组件,这意味着它有许多组件显示在顶部,其中任何一个都可能消耗鼠标事件

(来自How to Use Root Panes

你的 Window class 是有道理的,没有必要从 Canvas 扩展,因为 Window 在 AWT 中已经是 class ,也是一头雾水。

Main 不需要调用 Window,这只会增加混乱。一个组件不应该创建它自己的 window,这不是它的责任,相反,它应该被添加到一个容器中,调用者选择它的创建时间。

这个...

public void stop() {
    try {
        thread.join();
        running = false;
    } catch(Exception e) {
        e.printStackTrace();
    }
}

永远不会工作,因为循环正在等待 running 变为 false 并且 join 正在阻塞调用,线程永远不会退出。还要考虑到 running 已在不同线程中使用,并且您可能最终会遇到“脏 read/write” 场景。

我以前看过这段代码,所以无论你从哪里复制它,停下来寻找更好的来源。

你的主循环也很危险。它正在创建一个“疯狂循环”,这种循环会消耗 CPU 个周期,使其他线程从 运行ning(或 运行ning 尽可能频繁)中饿死,并且通常不会结束的性能问题。相反,您应该(至少)使用 Thread.yield 或者更好的是 Thread.sleep.

请记住,屏幕每秒只能刷新这么多次,因此更新 UI 超出该范围只是在浪费时间。一个“体面”的目标可能是 60fps。

delta += (now - lastTime) / ns;对我来说没有意义(但我很笨),你真正想知道的是运行最后一个更新周期所花费的时间以及多长时间您需要等待以保持帧速率,double delta = (now - lastTime) / ns; 更有意义(对我来说)。

您对 BufferStrategy 的使用也是错误的。 JavaDocs for BufferStrategy 有一个很好的例子,你应该如何使用它。

同样,我不知道您从哪里获得原始代码,但我不建议将来使用该来源。

可运行示例...

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MainSurface mainSurface = new MainSurface();
                JFrame frame = new JFrame();
                frame.add(mainSurface);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                mainSurface.start();
            }
        });
    }

    public class MainSurface extends Canvas {
        private volatile boolean running = false;
        private Thread thread;
//        NeuralNetwork neuralNetwork = new NeuralNetwork();

        private Point dotty;

        public MainSurface() {
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    dotty = e.getPoint();
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(500, 500);
        }

        public void start() {
            if (thread != null) {
                stop();
            }
            thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    makeItSo();
                }
            });
            thread.start();
            running = true;
        }

        public void stop() {
            try {
                running = false;
                thread.join();
            } catch (Exception e) {
                e.printStackTrace();
            }
            thread = null;
        }

        protected void makeItSo() {
            long lastTime = System.nanoTime();
            double fps = 1.0;
            double ns = 100000000 / fps;
            double delta = 0;

            createBufferStrategy(3);

            while (running) {
                long now = System.nanoTime();
                delta += (now - lastTime) / ns;
                lastTime = now;
                if (delta > 0) {
                    try {
                        Thread.sleep((int) delta);
                    } catch (InterruptedException ex) {
                    }
                }
//                while (delta >= 1) {
//                    tick();
//                    delta--;
//                }

                render();
            }
            stop();
        }

        public void tick() {
        }

        public void render() {
            BufferStrategy bs = null;
            while (bs == null) {
                bs = getBufferStrategy();
            }
            do {
                // The following loop ensures that the contents of the drawing buffer
                // are consistent in case the underlying surface was recreated
                do {
                    // Get a new graphics context every time through the loop
                    // to make sure the strategy is validated
                    Graphics2D g2d = (Graphics2D) bs.getDrawGraphics();
                    g2d.setColor(getBackground());
                    g2d.fillRect(0, 0, getWidth(), getHeight());

                    // Render to graphics
                    // ...
                    g2d.setColor(Color.RED);
                    int x = (getWidth() - 100) / 2;
                    int y = (getHeight() - 100) / 2;
                    g2d.fillRect(x, y, 100, 100);

                    if (dotty != null) {
                        x = dotty.x - 10;
                        y = dotty.y - 10;
                        g2d.setColor(Color.BLUE);
                        g2d.fillOval(x, y, 20, 20);
                    }
                    // Dispose the graphics
                    g2d.dispose();

                    // Repeat the rendering if the drawing buffer contents
                    // were restored
                } while (bs.contentsRestored());
                // Display the buffer
                bs.show();
                // Repeat the rendering if the drawing buffer was lost
            } while (bs.contentsLost());
        }
    }
}