Java Swing中如何在ActionListener内正确调用形状绘制方法
问题解决思路
核心问题逻辑说明:
- 你不能主动创建Graphics对象传入绘制方法,Swing中所有组件的绘制都是由系统调度,重写
paintComponent(Graphics g)方法时,系统会自动传入可用的Graphics对象 - 缺少专门的绘图容器,你没有定义用来承载图形的画布组件,无法触发绘制回调
- 按钮点击后不需要直接调用绘制方法,只需要修改绘制状态标记,调用
repaint()通知系统重绘画布即可
完整修改代码
1. 自定义画布组件 CanvasPanel.java
package com.company; import javax.swing.*; import java.awt.*; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; // 专门用来绘图的画布类,所有图形都画在这个组件上 public class CanvasPanel extends JPanel { // 存储所有需要绘制的图形逻辑,方便后续扩展其他形状 private final List<Consumer<Graphics>> drawTasks = new ArrayList<>(); public void addDrawTask(Consumer<Graphics> task) { drawTasks.add(task); // 添加后通知系统重绘 repaint(); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); // 执行所有已添加的绘制任务 for (Consumer<Graphics> task : drawTasks) { task.accept(g); } } }
2. 修改TestFrame.java
package com.company; import javax.swing.*; import java.awt.*; public class TestFrame extends JFrame{ // 初始化画布 private final CanvasPanel canvas = new CanvasPanel(); // 把画布传入绘图工具类 public final OvalDrawTool odt = new OvalDrawTool(canvas); public static void main(String[] args){ new TestFrame().start(); } public void start(){ setLayout(new BorderLayout()); JPanel buttonsPanel = new JPanel(); JButton buttonOval = odt.getButtonOval(); buttonsPanel.add(buttonOval); // 按钮放北部,画布放中间 add(buttonsPanel, BorderLayout.NORTH); add(canvas, BorderLayout.CENTER); setSize(500,500); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } }
3. 修改OvalDrawTool.java
package com.company; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class OvalDrawTool implements ActionListener{ // 持有画布引用,点击按钮后往画布加绘制任务 private final CanvasPanel canvas; public OvalDrawTool(CanvasPanel canvas) { this.canvas = canvas; } public JButton getButtonOval() { JButton buttonOval = new JButton(); buttonOval.setPreferredSize(new Dimension(100, 50)); buttonOval.setText("Oval"); buttonOval.addActionListener(this); return buttonOval; } public void paintOval(Graphics g) { g.setColor(Color.green); g.fillOval(100, 100, 50, 50); } @Override public void actionPerformed(ActionEvent e) { // 点击按钮后把椭圆绘制任务加到画布中 canvas.addDrawTask(this::paintOval); } }
扩展说明
- 后续要加新的图形,只需要新增对应的绘制工具类,往
CanvasPanel的drawTasks添加对应绘制逻辑即可,不需要修改现有画布和框架代码 - 每次调用
addDrawTask都会自动触发重绘,之前添加的图形不会丢失,点击多次按钮会叠加多个椭圆
内容的提问来源于stack exchange,提问作者I_was_made_for_java_you_baby
相关产品推荐
相关产品推荐

