You need to enable JavaScript to run this app. Java Swing 如何在JPanel绘制新矩形时保留多个已绘制矩形?
优惠活动
大模型
产品
解决方案
定价
更多

Java Swing 如何在JPanel绘制新矩形时保留多个已绘制矩形?

问题原因

原代码无法保留已绘制矩形的核心原因有两点:

  1. 每次触发repaint()时,paintComponent开头调用的super.paintComponent(g)会完全清空面板上的已有绘制内容
  2. 代码全局仅存储了当前正在拖拽的单个临时矩形的四个坐标,没有对已经完成绘制的矩形做持久化存储,重绘时自然无法还原之前的画面
具体修改步骤
  • 新增一个列表集合,专门存储所有已经完成、需要长期保留的矩形对象
  • 分离两类矩形的逻辑:拖拽过程中只更新临时矩形的实时坐标,等鼠标松开、确定本次绘制完成后,再将临时矩形转为标准格式存入已完成集合
  • 调整重绘逻辑:每次重绘时先遍历列表把所有已完成的矩形全部画出,最后再叠加绘制当前正在拖拽的临时矩形,保证拖拽时的实时预览效果和原生画图软件一致
修改后的完整代码
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;

public class DrawRect extends JPanel {
    // 存储所有已完成绘制、需要长期保留的矩形
    private final List<Rectangle> finishedRects = new ArrayList<>();
    // 当前正在拖拽的临时矩形的起点、终点坐标
    int x, y, x2, y2;

    public static void main(String[] args) {
        JFrame f = new JFrame("Draw Box Mouse 2");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setContentPane(new DrawRect());
        f.setSize(300, 300);
        f.setVisible(true);
    }

    DrawRect() {
        x = y = x2 = y2 = 0;
        MyMouseListener listener = new MyMouseListener();
        addMouseListener(listener);
        addMouseMotionListener(listener);
    }

    public void setStartPoint(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void setEndPoint(int x, int y) {
        x2 = x;
        y2 = y;
    }

    public void drawPerfectRect(Graphics g, int x, int y, int x2, int y2) {
        int px = Math.min(x,x2);
        int py = Math.min(y,y2);
        int pw=Math.abs(x-x2);
        int ph=Math.abs(y-y2);
        g.drawRect(px, py, pw, ph);
    }

    class MyMouseListener extends MouseAdapter {
        public void mousePressed(MouseEvent e) {
            setStartPoint(e.getX(), e.getY());
        }

        public void mouseDragged(MouseEvent e) {
            setEndPoint(e.getX(), e.getY());
            repaint();
        }

        public void mouseReleased(MouseEvent e) {
            setEndPoint(e.getX(), e.getY());
            // 计算当前拖拽的矩形的规范范围,仅当宽高大于0时才存入正式集合,避免误点产生无效图形
            int px = Math.min(x, x2);
            int py = Math.min(y, y2);
            int pw = Math.abs(x - x2);
            int ph = Math.abs(y - y2);
            if (pw > 0 && ph > 0) {
                finishedRects.add(new Rectangle(px, py, pw, ph));
            }
            repaint();
        }
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.RED);
        // 先绘制所有已经完成存储的矩形
        for (Rectangle rect : finishedRects) {
            g.drawRect(rect.x, rect.y, rect.width, rect.height);
        }
        // 最后绘制当前正在拖拽的临时预览矩形
        drawPerfectRect(g, x, y, x2, y2);
    }
}
效果说明

修改后实现的交互和Windows自带画图的矩形绘制逻辑完全一致:

  • 拖拽鼠标时可以实时看到跟随移动的矩形预览框
  • 鼠标松开后,当前绘制的矩形会固定保留在面板上,后续绘制新矩形时不会擦除已有内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.02 20:27:05