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

JFrame通过鼠标监听绘制矩形出现偏移及显示异常问题求助

问题原因及解决方案

1. 矩形绘制偏移问题

  • 根本原因:你将MouseListener绑定在了JFrame实例上,MouseEvent的getX()/getY()返回的是整个窗口(包含标题栏、窗口边框)的相对坐标,而你绘制矩形的JPanel坐标原点是窗口内容区的左上角,两者坐标系不匹配。你手动写的x-7、y-30是硬编码的当前系统下的边框、标题栏尺寸,换系统/主题就会失效,自然会出现偏移。
  • 修复方案:不要将鼠标监听器绑定到JFrame,统一绑定到负责绘制的自定义JPanel上,此时鼠标坐标和绘制坐标的坐标系完全一致,无需手动做偏移修正。

2. 新增图形必须重设窗口可见才显示的问题

  • 根本原因:
    1. Swing容器在已显示状态下新增/删除组件后,必须手动调用revalidate()触发布局重算、repaint()触发重绘,你当前只调用了pack(),没有触发重绘逻辑,所以新组件不会显示。
    2. JFrame默认使用BorderLayout布局,你每次调用add()新增Panel时,默认会覆盖BorderLayout.CENTER位置的旧组件,最终只会显示最后一个绘制的矩形,逻辑本身就有问题。
    3. 你自定义的Panel没有重写getPreferredSize()方法,调用pack()会导致窗口尺寸被重置为不符合预期的大小。
  • 优化&修复方案:不要每次新建JPanel来承载单个矩形,用一个固定的自定义JPanel维护所有要绘制的矩形列表,每次新增矩形时更新列表、调用repaint()即可,不需要动态新增组件。

核心修改后代码示例

统一的绘制Panel

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

public class DrawPanel extends JPanel {
    // 维护所有要绘制的矩形列表
    private List<Rectangle> rectangles = new ArrayList<>();

    public DrawPanel() {
        setBackground(Color.WHITE);
        // 把鼠标监听器直接绑定到绘制面板上
        MouseAdapter mouseListener = new MouseAdapter() {
            Point pressPoint;
            @Override
            public void mousePressed(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON1) {
                    pressPoint = e.getPoint();
                }
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON1 && pressPoint != null) {
                    int x = Math.min(pressPoint.x, e.getX());
                    int y = Math.min(pressPoint.y, e.getY());
                    int width = Math.abs(e.getX() - pressPoint.x);
                    int height = Math.abs(e.getY() - pressPoint.y);
                    rectangles.add(new Rectangle(x, y, width, height));
                    repaint(); // 直接触发重绘即可
                    pressPoint = null;
                }
            }
        };
        addMouseListener(mouseListener);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.BLACK);
        // 绘制所有矩形
        for (Rectangle rect : rectangles) {
            g.fillRect(rect.x, rect.y, rect.width, rect.height);
        }
    }

    // 固定面板首选大小,避免pack时尺寸错乱
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(800, 800);
    }
}

窗口初始化代码

import javax.swing.*;

public class Frame {
    private JFrame frame;

    public Frame() {
        frame = new JFrame("Graph");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 只添加一个固定的绘制面板
        frame.add(new DrawPanel());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        // Swing组件初始化必须放在事件调度线程执行
        SwingUtilities.invokeLater(Frame::new);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 19:54:03