You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Java Swing绘图昼夜切换按钮实现:ActionListener与g2变量访问求助

解决双扇窗日夜切换的ActionListener与绘图颜色修改问题

你遇到的问题其实很典型——要实现UI控件和绘图组件的交互,核心是用状态变量控制绘图逻辑,再通过按钮事件更新状态并触发重绘。我来一步步帮你解决:

核心思路

  1. DrawComponent添加一个状态变量(比如isDay),用来标记当前是白天还是黑夜。
  2. 在绘图方法里,根据这个状态变量动态选择天空、太阳/月亮的颜色,而不是写死固定颜色值。
  3. 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方法,用新的状态重新绘制组件。
  • 替换paintpaintComponent:Swing组件推荐使用paintComponent而不是直接重写paint,记得调用super.paintComponent(g)来完成组件的基础绘制工作。
  • 动态颜色选择:用三目运算符根据isDay的值选择不同的颜色,这样就不用直接操作g2变量,而是通过状态驱动绘图逻辑。

这样修改后,点击Day和Night按钮就能切换天空和太阳/月亮的颜色了,完美实现你的需求!

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

火山引擎 最新活动