You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Swing中基于mouseEntered与mouseExited事件实现人脸组件眼睛开闭功能的技术求助

Hey there! Let's break this down step by step since you're new to Swing—this is a great first project to get the hang of custom components and event listeners.

完整示例代码

Here's a working example that does exactly what you want: a face component that opens its eyes when the mouse enters, and closes them when it exits.

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

// 自定义人脸组件,同时实现MouseListener来处理鼠标事件
public class FaceComponent extends JComponent implements MouseListener {
    // 标记眼睛是否睁开的状态变量
    private boolean isEyesOpen = false;

    public FaceComponent() {
        // 给当前组件添加鼠标监听器(就是自己,因为实现了MouseListener接口)
        addMouseListener(this);
        // 设置组件的最小尺寸,不然可能显示不出来
        setPreferredSize(new Dimension(200, 200));
    }

    // 重写绘制方法,根据眼睛状态绘制不同的眼睛
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); // 必须调用父类方法,负责组件的背景绘制等

        // 画脸(一个黄色的圆)
        g.setColor(Color.YELLOW);
        g.fillOval(50, 50, 100, 100);

        // 画嘴巴(一条黑色的弧线)
        g.setColor(Color.BLACK);
        g.drawArc(70, 120, 60, 30, 0, 180);

        // 根据眼睛状态绘制眼睛
        if (isEyesOpen) {
            // 睁眼:两个黑色的椭圆
            g.fillOval(70, 80, 20, 15);
            g.fillOval(110, 80, 20, 15);
        } else {
            // 闭眼:两条黑色的直线
            g.drawLine(70, 88, 90, 88);
            g.drawLine(110, 88, 130, 88);
        }
    }

    // MouseListener接口的方法:鼠标进入组件时触发
    @Override
    public void mouseEntered(MouseEvent e) {
        isEyesOpen = true;
        repaint(); // 通知Swing重新绘制组件,这样眼睛状态的变化才会显示出来
    }

    // MouseListener接口的方法:鼠标退出组件时触发
    @Override
    public void mouseExited(MouseEvent e) {
        isEyesOpen = false;
        repaint();
    }

    // 下面这三个方法是MouseListener接口必须实现的,但我们暂时不需要,留空即可
    @Override
    public void mouseClicked(MouseEvent e) {}

    @Override
    public void mousePressed(MouseEvent e) {}

    @Override
    public void mouseReleased(MouseEvent e) {}

    // 测试用的主方法,把人脸组件放到窗口里显示
    public static void main(String[] args) {
        // Swing的操作要在事件调度线程(EDT)中执行,这是规范
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Face with Interactive Eyes");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new FaceComponent());
            frame.pack(); // 自动调整窗口大小以适应组件
            frame.setLocationRelativeTo(null); // 窗口居中显示
            frame.setVisible(true);
        });
    }
}
关键知识点解释

Let's go over the parts that are most important for your question:

  • 关联MouseListener: 在组件的构造方法里调用addMouseListener(this),因为我们的FaceComponent类自己实现了MouseListener接口,所以可以直接把自身作为监听器添加进去。
  • 状态变量与重绘: isEyesOpen用来记录眼睛的状态,每次状态改变后调用repaint(),这会告诉Swing去调用paintComponent()方法重新绘制组件,这样用户就能看到眼睛的变化了。
  • MouseListener接口: 因为这是一个接口,你必须实现它的所有5个方法,哪怕有些方法你暂时用不到(比如mouseClicked),可以留空实现。
针对新手的学习建议
  • 从核心概念入手: 先搞清楚Swing的基本组成:组件(Component)、容器(比如JFrame、JPanel)、事件监听模型(Listener)、绘制机制(paintComponent)。这些是Swing的基础,理解了之后再做复杂项目会轻松很多。
  • 从小项目练起: 不要一开始就搞复杂界面,先做一些简单的交互练习:比如让按钮点击后改变颜色,或者鼠标拖动时画图形,逐步熟悉事件监听和自定义绘制的逻辑。
  • 重视官方文档: 优先看Java官方的Swing核心教程,里面有大量关于自定义组件、事件处理的示例和详细解释,是最权威的学习资料。
  • 了解EDT: 记住Swing的所有组件操作和绘制都应该在**事件调度线程(EDT)**中进行,就像示例里的SwingUtilities.invokeLater()那样。虽然简单项目可能不会出问题,但养成这个习惯能避免后续很多奇怪的bug。

内容的提问来源于stack exchange,提问作者mailiee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 22:04:08