如何在一个类中使用两个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
相关产品推荐
相关产品推荐

