Java Swing调用repaint()重绘时将无关菜单栏绘制到绘图面板如何解决
问题原因
- 你重写
DrawPanel的paintComponent方法时,没有调用父类的super.paintComponent(g)方法:Swing的JPanel默认的paintComponent会完成填充背景色、清理上一次绘制残留内容的工作,缺少这行代码就会导致背景色不生效、上一次界面渲染的内容(包括左侧菜单栏的像素残留)不会被清除,直接和新绘制的图形叠加。 - 额外问题1:当前代码中绘制图形时没有对坐标差做绝对值处理,如果鼠标从右下往左上拖拽绘制,宽高为负数会导致图形无法正常显示。
- 额外问题2:当前
fillArc的参数传值错误,fillArc的参数顺序为(x坐标, y坐标, 宽度, 高度, 起始角度, 弧的角度),你传入的参数不符合规范会导致弧形绘制异常。 - 额外问题3:现有逻辑每次重绘只会显示最新绘制的一个图形,之前绘制的内容会被清除,如果需要保留历史绘制记录,需要额外存储历史图形数据。
修复方案
最简修复(仅解决背景不生效、菜单栏残留问题)
修改DrawPanel的paintComponent方法即可:
@Override public void paintComponent (Graphics g) { // 必须加这行,调用父类绘制逻辑清背景、渲染背景色 super.paintComponent(g); g.setColor(color); int drawX = Math.min(x1, x2); int drawY = Math.min(y1, y2); int drawW = Math.abs(x2 - x1); int drawH = Math.abs(y2 - y1); if (shape.equals("rectangle")) g.fillRect(drawX, drawY, drawW, drawH); else if (shape.equals("circle")) g.fillOval(drawX, drawY, drawW, drawH); else if (shape.equals("arc")) // 这里角度可根据你的需求调整,示例为绘制180度上半圆 g.fillArc(drawX, drawY, drawW, drawH, 0, 180); }
支持保留历史绘图的完整修复版
如果需要保留所有绘制过的图形,可使用修改后的完整DrawPanel代码:
import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.util.ArrayList; import java.util.List; public class DrawPanel extends JPanel implements MouseListener, MouseMotionListener { int x1, y1, x2, y2; Color color = Color.BLACK; String shape = "rectangle"; // 存储历史绘制的所有图形 List<ShapeItem> historyShapes = new ArrayList<>(); // 内部类存储单个图形的完整属性 static class ShapeItem { String type; Color color; int x, y, width, height; public ShapeItem(String type, Color color, int x, int y, int width, int height) { this.type = type; this.color = color; this.x = x; this.y = y; this.width = width; this.height = height; } } public DrawPanel() { addMouseListener(this); addMouseMotionListener(this); } @Override public void paintComponent (Graphics g) { super.paintComponent(g); // 绘制所有历史图形 for (ShapeItem item : historyShapes) { g.setColor(item.color); switch (item.type) { case "rectangle": g.fillRect(item.x, item.y, item.width, item.height); break; case "circle": g.fillOval(item.x, item.y, item.width, item.height); break; case "arc": g.fillArc(item.x, item.y, item.width, item.height, 0, 180); break; } } } public void mousePressed(MouseEvent e) { x1 = e.getX(); y1 = e.getY(); } public void mouseReleased(MouseEvent e) { x2 = e.getX(); y2 = e.getY(); int drawX = Math.min(x1, x2); int drawY = Math.min(y1, y2); int drawW = Math.abs(x2 - x1); int drawH = Math.abs(y2 - y1); // 把当前绘制完成的图形加入历史列表 historyShapes.add(new ShapeItem(shape, color, drawX, drawY, drawW, drawH)); repaint(); } public void setColor(Color color) { this.color = color; } public void setShape(String shape) { this.shape = shape; } // 清空画板方法,可绑定到你的Erase按钮 public void clearAll() { historyShapes.clear(); repaint(); } public void mouseClicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseDragged(MouseEvent e) {} public void mouseMoved(MouseEvent e) {} }
内容的提问来源于stack exchange,提问作者Mr. Goose
相关产品推荐
相关产品推荐

