Java Swing绘图昼夜切换按钮实现:ActionListener与g2变量访问求助
解决双扇窗日夜切换的ActionListener与绘图颜色修改问题
你遇到的问题其实很典型——要实现UI控件和绘图组件的交互,核心是用状态变量控制绘图逻辑,再通过按钮事件更新状态并触发重绘。我来一步步帮你解决:
核心思路
- 给
DrawComponent添加一个状态变量(比如isDay),用来标记当前是白天还是黑夜。 - 在绘图方法里,根据这个状态变量动态选择天空、太阳/月亮的颜色,而不是写死固定颜色值。
- 在
DrawingOne的构造方法里,给两个按钮添加ActionListener,点击时修改DrawComponent的状态,再调用repaint()方法触发组件重绘。
修改后的完整代码
import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*; public class DrawingOne extends JFrame{ public DrawingOne() { Container container = getContentPane(); container.setBackground(new Color(224, 196, 214)); container.setLayout(new BorderLayout(20, 20)); JButton j1 = new JButton("Day"); JButton j2 = new JButton("Night"); // 创建绘图组件实例,后续要在ActionListener里修改它的状态 DrawComponent c = new DrawComponent(); // Day按钮的事件监听 j1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { c.setDay(true); c.repaint(); // 触发重绘,让新的颜色生效 } }); // Night按钮的事件监听 j2.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { c.setDay(false); c.repaint(); } }); container.add(j1, BorderLayout.SOUTH); container.add(j2, BorderLayout.NORTH); add(c); setSize(DEFAULT_WITDH, DEFAULT_HEIGHT); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setVisible(true); } public static final int DEFAULT_WITDH = 700; public static final int DEFAULT_HEIGHT = 500; public static void main(String[] args) { DrawingOne frame = new DrawingOne(); } } class DrawComponent extends JComponent { // 状态变量:标记当前是否为白天 private boolean isDay = true; // 提供方法来修改状态 public void setDay(boolean day) { this.isDay = day; } @Override public void paintComponent(Graphics g) { super.paintComponent(g); // 别忘调用父类方法,确保组件绘制正确 Graphics2D g2 = (Graphics2D) g; // 窗口边框 Rectangle2D.Double rectangle2Drect2 = new Rectangle2D.Double(37, 26, 458, 280); g2.setStroke(new BasicStroke(3)); g2.setColor(Color.black); g2.draw(rectangle2Drect2); g2.setColor(Color.white); g2.fill(rectangle2Drect2); // 根据状态选择天空颜色 Color skyColor = isDay ? new Color(135, 206, 235) : new Color(25, 25, 112); // 左侧窗扇 rectangle2Drect2 = new Rectangle2D.Double(51, 40, 160, 250); g2.setStroke(new BasicStroke(3)); g2.setColor(Color.black); g2.draw(rectangle2Drect2); g2.setColor(skyColor); g2.fill(rectangle2Drect2); // 右侧窗扇 rectangle2Drect2 = new Rectangle2D.Double(230, 40, 250, 250); g2.setStroke(new BasicStroke(3)); g2.setColor(Color.black); g2.draw(rectangle2Drect2); g2.setColor(skyColor); g2.fill(rectangle2Drect2); // 把手底座 rectangle2Drect2 = new Rectangle2D.Double(215, 140, 10, 10); g2.setStroke(new BasicStroke(2)); g2.setColor(Color.black); g2.draw(rectangle2Drect2); g2.setColor(Color.white); g2.fill(rectangle2Drect2); // 把手 rectangle2Drect2 = new Rectangle2D.Double(217, 142, 4, 30); g2.setStroke(new BasicStroke(2)); g2.setColor(Color.black); g2.draw(rectangle2Drect2); g2.setColor(Color.white); g2.fill(rectangle2Drect2); // 根据状态选择太阳/月亮颜色 Color sunMoonColor = isDay ? Color.getHSBColor(0.548f, 0.426f, 0.922f) : new Color(240, 248, 255); g2.setColor(sunMoonColor); g2.fillOval(100, 60, 80, 80); // 花盆 int[] xpoints = {230 + 60, 300 + 60, 285 + 61, 244 + 60}; int[] ypoints = {240, 240, 290, 290}; int npoints = 4; g2.setColor(new Color(172, 86, 30)); g2.fillPolygon(xpoints, ypoints, npoints); // 花茎 g2.setStroke(new BasicStroke(5)); g2.setColor(new Color(0, 128, 0)); g2.drawLine(325, 200, 325, 238); // 花瓣 g2.setColor(new Color(255, 192, 203)); g2.fillOval(317, 200, 22, 22); g2.fillOval(317, 175, 22, 22); g2.fillOval(317 - 15, 190, 22, 22); g2.fillOval(317 + 13, 190, 22, 22); // 花心 g2.setColor(new Color(255, 165, 0)); g2.fillOval(317, 190, 15, 15); } }
关键修改点说明
- 状态变量
isDay:在DrawComponent里添加这个私有变量,用来控制颜色选择,同时提供setDay方法让外部修改状态。 - ActionListener的位置:在
DrawingOne的构造方法里,创建按钮后直接给它们添加监听,用匿名内部类实现非常方便。 - 重绘触发:每次修改状态后调用
repaint(),这会让系统自动调用paintComponent方法,用新的状态重新绘制组件。 - 替换
paint为paintComponent:Swing组件推荐使用paintComponent而不是直接重写paint,记得调用super.paintComponent(g)来完成组件的基础绘制工作。 - 动态颜色选择:用三目运算符根据
isDay的值选择不同的颜色,这样就不用直接操作g2变量,而是通过状态驱动绘图逻辑。
这样修改后,点击Day和Night按钮就能切换天空和太阳/月亮的颜色了,完美实现你的需求!
内容的提问来源于stack exchange,提问作者Ifwehadamonkey




