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

按钮事件触发时自定义JPanel Canvas无法绘制线条问题求助

问题原因

  • 错误缓存了Graphics对象引用:Swing中paintComponent传入的Graphics对象是临时的,仅在重绘周期内有效,你将其存为Canvas的成员变量g2d,在drawL中调用时该对象已经失效,绘制操作不会生效。
  • 绘制逻辑被覆盖:drawL中直接绘制的内容,会被后续触发的repaint调用的paintComponent方法完全覆盖,paintComponent中只绘制了初始线条和圆点,不会保留你动态绘制的内容。
  • Canvas组件未添加到窗口:你创建了canva实例,但没有将其添加到JFrame的内容面板中,组件本身都不可见,自然看不到绘制结果。
  • 构造方法命名错误:Window类的构造方法被命名为Ventana,和类名不一致,导致类初始化逻辑不会执行,属于基础语法错误。

解决方案

  1. 移除缓存的Graphics成员变量,所有绘制操作统一在paintComponent中执行
  2. 新增集合存储需要动态绘制的线条参数,每次点击按钮仅向集合中添加数据,触发重绘即可
  3. 将Canvas组件添加到窗口的内容面板
  4. 修正构造方法命名错误

修改后的Canvas类核心代码

public class Canvas extends JPanel {
    static final int SCREEN_WIDTH = 300;
    static final int SCREEN_HEIGHT = 300;
    // 存储动态添加的线条,每个元素保存起点、终点、颜色
    private final List<LineData> dynamicLines = new ArrayList<>();

    // 内部类存储线条参数
    private static class LineData {
        char posi;
        int posf;
        Color color;
        LineData(char posi, int posf, Color color) {
            this.posi = posi;
            this.posf = posf;
            this.color = color;
        }
    }

    public Canvas() {
        this.setPreferredSize(new Dimension(SCREEN_WIDTH,SCREEN_HEIGHT));
        this.setBackground(new Color(66, 64, 64));
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        // 绘制初始线条
        trazarLinea(g2d, 'a', 1, new Color(75, 201, 201));
        trazarLinea(g2d, 'b', 3, new Color(240, 20, 255));
        trazarLinea(g2d, 'c', 1, new Color(235, 64, 52));
        trazarLinea(g2d, 'd', 2, new Color(128, 64, 123));
        // 绘制动态添加的线条
        for (LineData line : dynamicLines) {
            trazarLinea(g2d, line.posi, line.posf, line.color);
        }
        dibujarCirculos(g2d);
    }

    public void dibujarCirculos(Graphics2D g2d) {
        g2d.setColor(new Color(230, 160, 30));
        g2d.fillOval(20, 20, 20, 20);
        g2d.fillOval(20, 97, 20, 20);
        g2d.fillOval(20, 182, 20, 20);
        g2d.fillOval(20, 255, 20, 20);
        g2d.fillOval(270, 20, 20, 20);
        g2d.fillOval(270, 97, 20, 20);
        g2d.fillOval(270, 182, 20, 20);
        g2d.fillOval(270, 255, 20, 20);
    }

    // 方法新增Graphics2D参数,使用传入的对象绘制
    public void trazarLinea(Graphics2D g2d, char posi, int posf, Color c) {
        final int X1 = 27;
        final int Y2 = 275;
        int y1 = 0, y2 = 0;
        g2d.setStroke(new BasicStroke(6));
        g2d.setColor(c);

        switch (posi) {
            case 'a': y1 = 30; break;
            case 'b': y1 = 109; break;
            case 'c': y1 = 194; break;
            case 'd': y1 = 264; break;
            default: y1 = 30;
        }
        switch (posf) {
            case 1: y2 = 30; break;
            case 2: y2 = 109; break;
            case 3: y2 = 194; break;
            case 4: y2 = 264; break;
            default: y2 = 30;
        }
        g2d.drawLine(X1, y1, Y2, y2);
    }

    public void drawL() {
        // 仅添加线条数据到集合,触发重绘即可
        dynamicLines.add(new LineData('a', 4, new Color(240, 20, 255)));
        repaint();
    }
}

修改后的Window类核心代码

public class Window extends JFrame {
    private JTextField txt_ubicacion;
    private JTextField txt_color;
    private JPanel panel_1;
    private Canvas canva;

    // 修正构造方法名称和类名一致
    public Window() {
        this.setPreferredSize(new Dimension(575, 330));
        this.setTitle("Relación de puntos - canvas");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(true);
        panel_1 = new JPanel();
        getContentPane().add(panel_1, BorderLayout.NORTH);
        iniciarComponentes();
        this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true); // 组件初始化完成后再显示窗口
    }

    public void iniciarComponentes() {
        canva = new Canvas();
        // 将canvas添加到窗口中央区域
        getContentPane().add(canva, BorderLayout.CENTER);
        
        JButton boton_dibujar = new JButton("Dibujar");
        boton_dibujar.addActionListener(e -> canva.drawL());
        boton_dibujar.setFocusPainted(false);
        boton_dibujar.setBackground(new Color(0, 139, 139));
        boton_dibujar.setFont(new Font("JetBrains Mono Medium", Font.PLAIN, 11));
        // 此处省略面板布局相关代码,确保按钮被添加到可见容器中即可
        panel_1.add(boton_dibujar);
    }

    public static void main(String[] args) {
        // Swing组件初始化要放在EDT线程中执行
        SwingUtilities.invokeLater(() -> new Window());
    }
}

内容的提问来源于stack exchange,提问作者Jugo de mora

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 16:15:00