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

使用Graphics对象绘制的线条创建标签后消失的技术问题

哦,这个问题我太熟了——你踩了Swing绘制机制里一个超常见的坑!

问题根源:临时的Graphics对象

你直接用jPanel1.getGraphics()拿到的Graphics对象是临时快照,它只对应组件当前这一刻的绘制上下文。一旦组件触发重绘(比如你添加JLabel后,布局管理器重新计算布局,必然会触发组件重绘),这个临时对象里的内容就会被清空,你画的线条自然就消失了。

Swing的绘制体系是基于「回调机制」的:组件会在需要更新画面时,自动调用paintComponent(Graphics g)方法完成绘制。直接获取Graphics绕开了这个机制,所以绘制内容根本无法持久。

正确的解决姿势:重写paintComponent方法

要让绘制的线条稳定显示,哪怕添加组件、窗口 resize 都不会消失,你需要自定义一个JPanel子类,重写它的paintComponent方法——这是Swing官方推荐的绘制方式。

修改后的代码示例

import java.awt.Color;
import java.awt.Graphics;
import java.awt.BorderLayout;
import javax.swing.*;

public class NewJFrame extends JFrame {
    // 用自定义绘制面板替代默认JPanel
    private DrawPanel drawPanel = new DrawPanel();
    private JLabel label = new JLabel("这是一个测试标签");
    private Object[][] busInfo = new Object[10][15];

    public NewJFrame() {
        initComponents();
    }

    @SuppressWarnings("unchecked")
    private void initComponents() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(400, 300);
        getContentPane().setLayout(new BorderLayout());
        
        // 添加自定义绘制面板到窗口中心
        getContentPane().add(drawPanel, BorderLayout.CENTER);
        // 添加标签到窗口底部
        getContentPane().add(label, BorderLayout.SOUTH);
        
        setVisible(true);
    }

    // 自定义绘制面板类
    class DrawPanel extends JPanel {
        @Override
        protected void paintComponent(Graphics g) {
            // 必须先调用父类方法,完成组件默认绘制(比如背景、边框),否则会有残影
            super.paintComponent(g);
            
            // 在这里写你的绘制逻辑
            g.setColor(Color.RED);
            g.drawLine(50, 50, 250, 200); // 示例:画一条从(50,50)到(250,200)的红线
        }
    }

    public static void main(String[] args) {
        // 确保在Swing事件调度线程中创建窗口,避免线程安全问题
        SwingUtilities.invokeLater(() -> new NewJFrame());
    }
}

额外注意事项

  • 永远不要直接调用paintComponent方法,要通过repaint()触发重绘,Swing会自动在正确的时机执行绘制。
  • 如果需要动态修改绘制内容(比如按钮点击后改变线条颜色),可以在DrawPanel里加成员变量存储绘制参数(比如private Color lineColor = Color.RED;),再提供set方法,在set方法里调用repaint()即可。
  • Swing的所有UI操作都要在事件调度线程(EDT)中执行,用SwingUtilities.invokeLater包裹窗口创建逻辑是最佳实践。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:13:47