一个挥杆新手,想做一个小小的移动眼睛Java GUI练习却卡住了

一个挥杆新手,想做一个小小的移动眼睛Java GUI练习却卡住了,java,swing,Java,Swing,我想实现一个面板,绘制两只眼睛,根据鼠标光标是在眼睛上方、内部还是下方向上、中间还是向下移动。我首先使用这个代码来制作眼睛: public class EyesPanel extends JPanel implements ActionListener { // images public void paintComponent(Graphics g) { super.paintComponents(g); g.drawOval(130, 100,

我想实现一个面板,绘制两只眼睛,根据鼠标光标是在眼睛上方、内部还是下方向上、中间还是向下移动。我首先使用这个代码来制作眼睛:

public class EyesPanel extends JPanel implements ActionListener {
    // images
    public void paintComponent(Graphics g) {
        super.paintComponents(g);
        g.drawOval(130, 100, 120, 120);
        g.drawOval(250, 100, 120, 120);
        g.fillOval(175, y, 30, 30);   // x: 175  y: 145
        g.fillOval(295, y, 30, 30);   // x: 295  y: 145
    }

然后是时候添加事件监听器来让这个类工作了,但这里是我坚持的部分。我知道如何使图形移动(ActionListener),我知道如何实现MouseInputListener(扩展MouseInputListener)。然而,将这两者结合在一起让我感到沮丧。谁能告诉我怎么做,给我一个示例代码真的很有帮助

以下是迄今为止我的代码,不是一个运行正常且完整的代码:

public class EyesPanel extends JPanel implements ActionListener {
    private JPanel panel;
    private int y;
    private int dy;
    private Timer t;
    private Mouse move;

    public EyesPanel() {
        dy = 5;
        y = 145;

        // mouse detector
        this.addMouseListener(new Mouse());
        this.addMouseMotionListener(new Mouse());

        // Timer 
        t = new Timer(100, this);
    }

    // images
    public void paintComponent(Graphics g) {
        super.paintComponents(g);
        g.drawOval(130, 100, 120, 120);
        g.drawOval(250, 100, 120, 120);
        g.fillOval(175, y, 30, 30);   // x: 175  y: 145
        g.fillOval(295, y, 30, 30);   // x: 295  y: 145
    }

    public void actionPerformed(ActionEvent event) {
        moveDown();     //➜ not complete, don't know how to implement
    }

    // move up
    private void moveUp() {
        if (move.move() == 1) {
            t.start();
            y = y + dy;
            repaint();
        } else {
            t.stop();
        }
    }

    // move down
    private void moveDown() {
        if (move.move() == -1) {
            t.start();
            y = y - dy;
            repaint();
        } else {
            t.stop();
        }
    }
    // ➜ not complete, trying, but no clue
}
我的鼠标事件类:

public class Mouse extends MouseInputAdapter {
    private int y;

    public void mouseEntered(MouseEvent event) {
        JPanel pane =  (JPanel) event.getSource();
        y = pane.getHeight();      // ➜ not complete
    }
}

您正在寻找方法
mouseMoved
而不是
mouseEntered

使您的类像这样,并且您的gota从super.paintComponents(g)上取下s

导入java.awt.Graphics;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.MouseEvent;
导入java.awt.event.MouseMotionListener;
导入java.util.Timer;
导入javax.swing.JPanel;
公共类EyesPanel扩展JPanel实现ActionListener、MouseMotionListener{
私人JPanel小组;
私营企业;
私家侦探;
私人定时器t;
公共事务委员会(){
dy=5;
y=145;
//鼠标检测器
this.addMouseMotionListener(this);
//计时器
}
//图像
公共组件(图形g){
超级组件(g);
g、 drawOval(130100120120);
g、 drawOval(250100120120);
g、 圆角(175,y,30,30);/x:175 y:145
g、 圆角(295,y,30,30);/x:295 y:145
}
//上移
// ➜ 不完整,尝试,但没有线索
@凌驾
已执行的公共无效操作(操作事件arg0){
//TODO自动生成的方法存根
}
@凌驾
公共无效鼠标标记(鼠标事件arg0){
//TODO自动生成的方法存根
}
@凌驾
public void mouseMoved(MouseEvent arg0){
//TODO自动生成的方法存根
System.out.println(arg0.getY());
if(arg0.getY()>101&&arg0.getY()<187)
y=arg0.getY();
重新油漆();
}
}

让眼睛跟随光标的数学原理并不复杂

下面是我的GUI的外观

  • 我创建了一个Eye类来固定外眼窝的中心和内眼球的中心

  • 我创建了一个MovingEyes类来创建JFrame,并创建了一个DrawingPanel类来在DrawingPanel上绘制眼睛。我在MovingEyes类的构造函数中创建了眼睛数组来容纳2只眼睛

  • DrawingPanel类的paintComponent方法除了画眼睛之外,什么也不做。黑眼球中心的计算在另一类中进行。我创建了两种方便的方法,这样我就可以画一个圆,并使用圆心和半径填充一个圆

  • EyeballListener类执行两个黑色眼球的计算。我们计算从眼窝中心到鼠标指针的线的θ角(弧度)。然后,我们使用θ角和眼球距离计算黑眼球的x和y位置

  • 这是密码

    package com.ggl.testing;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Point;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseMotionAdapter;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class MovingEyes implements Runnable {
    
        private static final int drawingWidth = 400;
        private static final int drawingHeight = 400;
        private static final int eyeballHeight = 150;
        private static final int eyeballWidthMargin = 125;
        private static final int eyeballOuterRadius = 50;
        private static final int eyeballInnerRadius = 20;
    
        private DrawingPanel drawingPanel;
    
        private Eye[] eyes;
    
        private JFrame frame;
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new MovingEyes());
        }
    
        public MovingEyes() {
            this.eyes = new Eye[2];
            this.eyes[0] = new Eye(new Point(eyeballWidthMargin, eyeballHeight));
            this.eyes[1] = new Eye(new Point(drawingWidth - eyeballWidthMargin,
                    eyeballHeight));
        }
    
        @Override
        public void run() {
            frame = new JFrame("Moving Eyes");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            drawingPanel = new DrawingPanel();
            frame.add(drawingPanel);
    
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        public class DrawingPanel extends JPanel {
    
            private static final long serialVersionUID = -2977860217912678180L;
    
            public DrawingPanel() {
                this.addMouseMotionListener(new EyeballListener());
                this.setBackground(Color.WHITE);
                this.setPreferredSize(new Dimension(drawingWidth, drawingHeight));
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
    
                g.setColor(Color.BLACK);
    
                for (Eye eye : eyes) {
                    drawCircle(g, eye.getOrigin(), eyeballOuterRadius);
                    fillCircle(g, eye.getEyeballOrigin(), eyeballInnerRadius);
                }
            }
    
            private void drawCircle(Graphics g, Point origin, int radius) {
                g.drawOval(origin.x - radius, origin.y - radius, radius + radius,
                        radius + radius);
            }
    
            private void fillCircle(Graphics g, Point origin, int radius) {
                g.fillOval(origin.x - radius, origin.y - radius, radius + radius,
                        radius + radius);
            }
    
        }
    
        public class Eye {
            private final Point origin;
            private Point eyeballOrigin;
    
            public Eye(Point origin) {
                this.origin = origin;
                this.eyeballOrigin = origin;
            }
    
            public Point getEyeballOrigin() {
                return eyeballOrigin;
            }
    
            public void setEyeballOrigin(Point eyeballOrigin) {
                this.eyeballOrigin = eyeballOrigin;
            }
    
            public Point getOrigin() {
                return origin;
            }
    
        }
    
        public class EyeballListener extends MouseMotionAdapter {
    
            private final double eyeballDistance = eyeballOuterRadius
                    - eyeballInnerRadius - 5;
    
            @Override
            public void mouseMoved(MouseEvent event) {
                Point p = event.getPoint();
                for (Eye eye : eyes) {
                    Point origin = eye.getOrigin();
                    double theta = Math.atan2((double) (p.y - origin.y),
                            (double) (p.x - origin.x));
                    int x = (int) Math.round(Math.cos(theta) * eyeballDistance)
                            + origin.x;
                    int y = (int) Math.round(Math.sin(theta) * eyeballDistance)
                            + origin.y;
                    eye.setEyeballOrigin(new Point(x, y));
                }
    
                drawingPanel.repaint();
            }
    
        }
    
    }
    

    看看这里:您不需要任何ActionListener或计时器。你需要的是一个MouseMotionListener。在其mouseMoved()方法中,存储鼠标的新坐标,然后调用repaint()。在paintComponent()中,使用鼠标坐标计算眼睛应注视的位置。
    package com.ggl.testing;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Point;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseMotionAdapter;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class MovingEyes implements Runnable {
    
        private static final int drawingWidth = 400;
        private static final int drawingHeight = 400;
        private static final int eyeballHeight = 150;
        private static final int eyeballWidthMargin = 125;
        private static final int eyeballOuterRadius = 50;
        private static final int eyeballInnerRadius = 20;
    
        private DrawingPanel drawingPanel;
    
        private Eye[] eyes;
    
        private JFrame frame;
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new MovingEyes());
        }
    
        public MovingEyes() {
            this.eyes = new Eye[2];
            this.eyes[0] = new Eye(new Point(eyeballWidthMargin, eyeballHeight));
            this.eyes[1] = new Eye(new Point(drawingWidth - eyeballWidthMargin,
                    eyeballHeight));
        }
    
        @Override
        public void run() {
            frame = new JFrame("Moving Eyes");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            drawingPanel = new DrawingPanel();
            frame.add(drawingPanel);
    
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        public class DrawingPanel extends JPanel {
    
            private static final long serialVersionUID = -2977860217912678180L;
    
            public DrawingPanel() {
                this.addMouseMotionListener(new EyeballListener());
                this.setBackground(Color.WHITE);
                this.setPreferredSize(new Dimension(drawingWidth, drawingHeight));
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
    
                g.setColor(Color.BLACK);
    
                for (Eye eye : eyes) {
                    drawCircle(g, eye.getOrigin(), eyeballOuterRadius);
                    fillCircle(g, eye.getEyeballOrigin(), eyeballInnerRadius);
                }
            }
    
            private void drawCircle(Graphics g, Point origin, int radius) {
                g.drawOval(origin.x - radius, origin.y - radius, radius + radius,
                        radius + radius);
            }
    
            private void fillCircle(Graphics g, Point origin, int radius) {
                g.fillOval(origin.x - radius, origin.y - radius, radius + radius,
                        radius + radius);
            }
    
        }
    
        public class Eye {
            private final Point origin;
            private Point eyeballOrigin;
    
            public Eye(Point origin) {
                this.origin = origin;
                this.eyeballOrigin = origin;
            }
    
            public Point getEyeballOrigin() {
                return eyeballOrigin;
            }
    
            public void setEyeballOrigin(Point eyeballOrigin) {
                this.eyeballOrigin = eyeballOrigin;
            }
    
            public Point getOrigin() {
                return origin;
            }
    
        }
    
        public class EyeballListener extends MouseMotionAdapter {
    
            private final double eyeballDistance = eyeballOuterRadius
                    - eyeballInnerRadius - 5;
    
            @Override
            public void mouseMoved(MouseEvent event) {
                Point p = event.getPoint();
                for (Eye eye : eyes) {
                    Point origin = eye.getOrigin();
                    double theta = Math.atan2((double) (p.y - origin.y),
                            (double) (p.x - origin.x));
                    int x = (int) Math.round(Math.cos(theta) * eyeballDistance)
                            + origin.x;
                    int y = (int) Math.round(Math.sin(theta) * eyeballDistance)
                            + origin.y;
                    eye.setEyeballOrigin(new Point(x, y));
                }
    
                drawingPanel.repaint();
            }
    
        }
    
    }