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

如何在一个类中使用两个propertyChange方法实现控件独立控制图形大小?

实现分步控制正方形和圆形尺寸的方案

其实核心问题就是要让两个StepPanel的尺寸变化事件能被区分开,这样Picture类就知道该更新哪个图形的尺寸了。我给你梳理一套低耦合、易扩展的实现思路:

1. 先给图形做个类型标识

首先定义一个枚举来区分不同的图形,这样后续加新图形也方便扩展:

public enum ShapeType {
    SQUARE, CIRCLE
}

2. 修改StepPanel,让它知道自己控制哪个图形

给StepPanel加一个ShapeType属性,并且在触发尺寸变化时,用不同的属性名来发送事件:

public class StepPanel extends JPanel {
    private ShapeType targetShape;
    private int currentSize = 50; // 默认初始尺寸

    // 构造方法传入目标图形类型
    public StepPanel(ShapeType targetShape) {
        this.targetShape = targetShape;
        // 这里保留你原来的增减按钮初始化逻辑
        initButtons();
    }

    private void initButtons() {
        JButton increaseBtn = new JButton("+");
        increaseBtn.addActionListener(e -> updateSize(10));
        
        JButton decreaseBtn = new JButton("-");
        decreaseBtn.addActionListener(e -> updateSize(-10));
        
        // 把按钮添加到面板的逻辑...
    }

    private void updateSize(int delta) {
        currentSize = Math.max(10, currentSize + delta); // 防止尺寸过小
        // 根据目标图形生成对应的属性名
        String propertyName = targetShape == ShapeType.SQUARE ? "squareSize" : "circleSize";
        // 触发属性变化事件
        firePropertyChange(propertyName, null, currentSize);
    }
}

3. 让Picture类区分事件,更新对应图形

修改Picture的propertyChange方法,根据事件的属性名来决定更新正方形还是圆形:

public class Picture extends Canvas implements PropertyChangeListener {
    private Rectangle square;
    private Circle circle;

    public Picture() {
        // 初始化默认尺寸的正方形和圆形
        square = new Rectangle(50, 50, 50, 50);
        circle = new Circle(200, 100, 25); // 假设Circle的构造是(x,y,radius)
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        switch (evt.getPropertyName()) {
            case "squareSize":
                int newSquareSize = (int) evt.getNewValue();
                // 更新正方形尺寸,同时保持居中(可选,根据你的布局需求调整)
                square.setSize(newSquareSize, newSquareSize);
                square.setLocation((getWidth() - newSquareSize)/2, (getHeight() - newSquareSize)/2);
                break;
            case "circleSize":
                int newCircleSize = (int) evt.getNewValue();
                // 更新圆形半径,同样保持居中
                circle.setRadius(newCircleSize / 2);
                circle.setCenter(getWidth()/2 + 100, getHeight()/2); // 假设和正方形错开位置
                break;
        }
        repaint(); // 刷新画布显示最新图形
    }

    // 重写paint方法绘制图形的逻辑...
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.drawRect(square.x, square.y, square.width, square.height);
        g.drawOval(circle.getCenterX() - circle.getRadius(), circle.getCenterY() - circle.getRadius(),
                   circle.getRadius()*2, circle.getRadius()*2);
    }
}

4. 让InitialField对应显示指定图形的尺寸

同样给InitialField绑定对应的图形类型,监听指定的属性变化:

public class InitialField extends JLabel {
    public InitialField(ShapeType targetShape) {
        String shapeName = targetShape == ShapeType.SQUARE ? "正方形" : "圆形";
        setText("当前" + shapeName + "尺寸: 50");
    }

    // 绑定对应的StepPanel事件
    public void bindToStepPanel(StepPanel stepPanel, ShapeType targetShape) {
        String propertyName = targetShape == ShapeType.SQUARE ? "squareSize" : "circleSize";
        stepPanel.addPropertyChangeListener(evt -> {
            if (propertyName.equals(evt.getPropertyName())) {
                String shapeName = targetShape == ShapeType.SQUARE ? "正方形" : "圆形";
                setText("当前" + shapeName + "尺寸: " + evt.getNewValue());
            }
        });
    }
}

5. 最后在主窗口中组装所有组件

public class MainWindow extends JFrame {
    public MainWindow() {
        setTitle("图形尺寸控制器");
        setSize(400, 300);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        // 创建组件实例
        Picture picture = new Picture();
        StepPanel squareStepPanel = new StepPanel(ShapeType.SQUARE);
        StepPanel circleStepPanel = new StepPanel(ShapeType.CIRCLE);
        InitialField squareField = new InitialField(ShapeType.SQUARE);
        InitialField circleField = new InitialField(ShapeType.CIRCLE);

        // 绑定事件
        squareStepPanel.addPropertyChangeListener(picture);
        squareField.bindToStepPanel(squareStepPanel, ShapeType.SQUARE);
        
        circleStepPanel.addPropertyChangeListener(picture);
        circleField.bindToStepPanel(circleStepPanel, ShapeType.CIRCLE);

        // 组装布局
        JPanel controlPanel = new JPanel(new GridLayout(2, 2));
        controlPanel.add(new JLabel("正方形控制器:"));
        controlPanel.add(squareStepPanel);
        controlPanel.add(new JLabel("圆形控制器:"));
        controlPanel.add(circleStepPanel);

        JPanel infoPanel = new JPanel(new GridLayout(1, 2));
        infoPanel.add(squareField);
        infoPanel.add(circleField);

        add(picture, BorderLayout.CENTER);
        add(controlPanel, BorderLayout.NORTH);
        add(infoPanel, BorderLayout.SOUTH);

        setVisible(true);
    }

    public static void main(String[] args) {
        new MainWindow();
    }
}

这个方案的好处是耦合度很低,后续如果要加三角形、椭圆这类新图形,只需要加一个ShapeType枚举值,再创建对应的StepPanel和InitialField就行,不需要修改现有核心逻辑。

内容的提问来源于stack exchange,提问作者k.gerilovski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:22:06