Java Swing 如何在JPanel绘制新矩形时保留多个已绘制矩形?
问题原因
原代码无法保留已绘制矩形的核心原因有两点:
- 每次触发
repaint()时,paintComponent开头调用的super.paintComponent(g)会完全清空面板上的已有绘制内容 - 代码全局仅存储了当前正在拖拽的单个临时矩形的四个坐标,没有对已经完成绘制的矩形做持久化存储,重绘时自然无法还原之前的画面
具体修改步骤
- 新增一个列表集合,专门存储所有已经完成、需要长期保留的矩形对象
- 分离两类矩形的逻辑:拖拽过程中只更新临时矩形的实时坐标,等鼠标松开、确定本次绘制完成后,再将临时矩形转为标准格式存入已完成集合
- 调整重绘逻辑:每次重绘时先遍历列表把所有已完成的矩形全部画出,最后再叠加绘制当前正在拖拽的临时矩形,保证拖拽时的实时预览效果和原生画图软件一致
修改后的完整代码
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
相关产品推荐
相关产品推荐

