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

Java AWT无Swing鼠标绘线:窗口缩放后线条消失求助

解决AWT Canvas绘制线条最小化后消失的问题

嘿,这个问题我太熟悉了!你遇到的情况是AWT组件重绘机制导致的——当窗口最小化再恢复时,系统会重新绘制Canvas,而你直接用getGraphics()画的内容是临时的,不会被持久保存,所以一刷新就没了。下面给你说清楚怎么解决:

问题根源

AWT的Canvas默认在需要重绘(比如窗口状态变化、组件大小改变)时,会调用paint()方法,这个方法默认会清空画布。你之前用c.getGraphics()获取的绘图上下文是临时的,画上去的内容不会被系统记录,所以重绘后就消失了。

解决方案:持久化绘制数据并重写paint方法

我们需要把所有绘制的线条保存起来,每次重绘时重新把这些线条画出来,步骤如下:

  • 用一个集合存储所有线条的坐标信息(比如每条线的起点和终点)
  • 重写Canvas的paint()方法,遍历集合重新绘制所有线条
  • 在鼠标拖拽时,把新的线条数据加入集合,然后触发重绘

修改后的完整代码

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;

class Drawing extends WindowAdapter implements MouseMotionListener, MouseListener, ComponentListener {
    Frame f;
    Canvas c;
    int X=400,Y=400;
    int px=-1,py=-1;
    // 用ArrayList存储所有线条,每个元素是一个包含4个int的数组:[起点x,起点y,终点x,终点y]
    ArrayList<int[]> lines = new ArrayList<>();

    public Drawing() {
        f=new Frame("Drawing - Canvas");
        f.addWindowListener(this);
        f.addComponentListener(this);
        f.setSize(X,Y);
        // 重写Canvas的paint方法
        c=new Canvas(){
            @Override
            public void paint(Graphics g) {
                super.paint(g);
                // 遍历所有线条,重新绘制
                for(int[] line : lines){
                    g.drawLine(line[0], line[1], line[2], line[3]);
                }
            }
        };
        f.add(c);
        c.addMouseMotionListener(this);
        c.addMouseListener(this);
        f.setVisible(true);
    }

    // 以下是你原来的空实现,保留即可
    public void componentResized(ComponentEvent e) {}
    public void componentHidden(ComponentEvent e) {}
    public void componentMoved(ComponentEvent e) {}
    public void componentShown(ComponentEvent e) {}
    public void mouseMoved(MouseEvent e) {}
    public void mouseClicked(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mousePressed(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}

    public void mouseDragged(MouseEvent e) {
        int x=e.getX();
        int y=e.getY();
        if(px!=-1) {
            // 把线条数据加入集合
            lines.add(new int[]{px, py, x, y});
            // 触发重绘,让paint方法重新画所有线条
            c.repaint();
        }
        px=x;
        py=y;
    }

    public void mouseReleased(MouseEvent e) {
        this.px=-1;
        this.py=-1;
    }

    public void windowClosing(WindowEvent e) {
        f.dispose();
    }

    public static void main(String[] args) {
        Drawing c=new Drawing();
    }
}

关键改动说明

  1. 新增了ArrayList<int[]> lines来存储每一条绘制的线条,每条线用四个整数记录起点和终点坐标
  2. 创建Canvas时重写了paint()方法,每次重绘都会遍历集合把所有线条重新画一遍
  3. mouseDragged()里不再直接用getGraphics()画线,而是把线条数据存入集合,然后调用repaint()触发系统重绘
  4. 移除了mouseReleased()里不必要的X和Y赋值

这样修改后,不管窗口怎么最小化、最大化或者调整大小,绘制的线条都会被持久保存并重新绘制出来啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:42:28