让两个同级的 Swing 组件交互
Letting two same-level Swing components interact
我正在尝试制作一个应用程序,但目前对如何整齐地构建我的代码有点困惑。
为简单起见,假设我想要一个 JFrame
包含:
- 一个
JPanel
,其中包含一个 JComboBox
,用户可以在其中 select 一个形状(正方形、圆形等)。
- 一个单独的
JPanel
,直观地显示 JComboBox
中的 selected 形状。
所以我有以下代码:
public class Frame extends JFrame {
Frame() {
ComboBoxPanel comboBoxPanel = new ComboBoxPanel();
ShapePanel shapePanel = new ShapePanel();
this.getContentPane().add(comboBoxPanel, BorderLayout.WEST);
this.getContentPane().add(shapePanel, BorderLayout.CENTER);
this.setResizable(true);
this.pack();
this.setVisible(true);
}
public static void main(String[] args) {
new Frame();
}
}
组合框面板:
public class ComboBoxPanel extends JPanel {
private JComboBox<Shape> comboBox;
ComboBoxPanel() {
comboBox = new JComboBox<Shape>(Shape.SHAPES);
this.add(comboBox);
comboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
// Here I want to repaint the shapePanel
}
}
});
}
}
最后,ShapePanel 看起来像:
public class ShapePanel extends JPanel {
@Override
public void paintComponent(Graphics g) {
// Get selected Shape from JComboBox and draw it
}
}
简而言之,如何让这两个同级组件以一种整洁的方式相互交互?我想到了一些解决方案,但它们看起来真的很脏。欢迎任何想法。
谢谢。
我建议阅读观察者模式或 mvc 模式。最好的解决方案可能是 mvc。在 MVC(模型、视图、控制器)中,您将模型(您的数据)保存在视图(两个 jpanels)之外。然后,因为两个面板共享相同的数据,所以很容易让您的显示面板由您的输入面板驱动。
如果您的 ComboBoxPanel
和 ShapePanel
都位于同一个 JFrame 中,则它们应该 "see" 彼此。从那里,您可以只使用 类 中的 getter 和 setter 来访问彼此的属性。
如果你在谈论不相关的 类,你总是可以采用一种设计模式,例如 类 签署合同并通过方法公开感兴趣的行为的观察者模式。
我在这里使用观察者模式写了一个详细的例子:
如果您有兴趣将用户界面和逻辑实现分开。 MVC 是另一个可行的选择。您的 Model 将仅包含您的逻辑和数据,而您的 View 仅包含您的 UI.
Model和View不需要知道对方的存在。您将使用链接视图和模型的 Controller。这样它就大大解耦了你的代码。所以有一天,如果你决定改变你的逻辑,UI 不受影响。
如果您决定更改 UI,逻辑也不受影响。
甚至可以结合观察者模式和 MVC。毕竟,这取决于你想要达到什么。
我正在尝试制作一个应用程序,但目前对如何整齐地构建我的代码有点困惑。
为简单起见,假设我想要一个 JFrame
包含:
- 一个
JPanel
,其中包含一个JComboBox
,用户可以在其中 select 一个形状(正方形、圆形等)。 - 一个单独的
JPanel
,直观地显示JComboBox
中的 selected 形状。
所以我有以下代码:
public class Frame extends JFrame {
Frame() {
ComboBoxPanel comboBoxPanel = new ComboBoxPanel();
ShapePanel shapePanel = new ShapePanel();
this.getContentPane().add(comboBoxPanel, BorderLayout.WEST);
this.getContentPane().add(shapePanel, BorderLayout.CENTER);
this.setResizable(true);
this.pack();
this.setVisible(true);
}
public static void main(String[] args) {
new Frame();
}
}
组合框面板:
public class ComboBoxPanel extends JPanel {
private JComboBox<Shape> comboBox;
ComboBoxPanel() {
comboBox = new JComboBox<Shape>(Shape.SHAPES);
this.add(comboBox);
comboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
// Here I want to repaint the shapePanel
}
}
});
}
}
最后,ShapePanel 看起来像:
public class ShapePanel extends JPanel {
@Override
public void paintComponent(Graphics g) {
// Get selected Shape from JComboBox and draw it
}
}
简而言之,如何让这两个同级组件以一种整洁的方式相互交互?我想到了一些解决方案,但它们看起来真的很脏。欢迎任何想法。
谢谢。
我建议阅读观察者模式或 mvc 模式。最好的解决方案可能是 mvc。在 MVC(模型、视图、控制器)中,您将模型(您的数据)保存在视图(两个 jpanels)之外。然后,因为两个面板共享相同的数据,所以很容易让您的显示面板由您的输入面板驱动。
如果您的 ComboBoxPanel
和 ShapePanel
都位于同一个 JFrame 中,则它们应该 "see" 彼此。从那里,您可以只使用 类 中的 getter 和 setter 来访问彼此的属性。
如果你在谈论不相关的 类,你总是可以采用一种设计模式,例如 类 签署合同并通过方法公开感兴趣的行为的观察者模式。
我在这里使用观察者模式写了一个详细的例子:
如果您有兴趣将用户界面和逻辑实现分开。 MVC 是另一个可行的选择。您的 Model 将仅包含您的逻辑和数据,而您的 View 仅包含您的 UI.
Model和View不需要知道对方的存在。您将使用链接视图和模型的 Controller。这样它就大大解耦了你的代码。所以有一天,如果你决定改变你的逻辑,UI 不受影响。
如果您决定更改 UI,逻辑也不受影响。
甚至可以结合观察者模式和 MVC。毕竟,这取决于你想要达到什么。