【问题标题】:Letting two same-level Swing components interact让两个同级 Swing 组件交互
【发布时间】:2016-07-05 09:34:25
【问题描述】:

我正在尝试制作一个应用程序,但目前有点卡在如何整齐地构建我的代码。

为简单起见,假设我想要一个 JFrame,其中包含:

  1. 一个JPanel,其中包含一个JComboBox,用户可以在其中选择一个形状(正方形、圆形等)。
  2. 一个单独的JPanel,在JComboBox 中直观地显示所选形状。

所以我有以下代码:

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
    }
}

简而言之,我怎样才能让这两个同级组件以一种简洁的方式相互交互?我已经想到了一些解决方案,但它们看起来真的很脏。欢迎任何想法。

谢谢。

【问题讨论】:

标签: java swing components


【解决方案1】:

如果您的ComboBoxPanelShapePanel 都驻留在同一个JFrame 中,那么它们将“看到”彼此。从那里,您可以使用两个类中的 getter 和 setter 来访问彼此的属性。

如果您谈论的是不相关的类,您总是可以采用一种设计模式,例如观察者模式,其中类签署合同并通过方法公开感兴趣的行为。

我在这里使用观察者模式写了一个详细的例子:Updating Change to another class


如果您有兴趣将用户界面和逻辑实现分开。 MVC 是另一个可行的选择。您的 Model 将仅包含您的逻辑和数据,而您的 View 仅包含您的 UI。

ModelView不需要知道彼此的存在。您将使用链接视图和模型的 Controller。这样,它极大地解耦了您的代码。所以有一天,如果你决定改变你的逻辑,UI 不会受到影响。

如果您决定更改 UI,逻辑也不受影响。


甚至可以将观察者模式和 MVC 结合起来。毕竟,这取决于您要实现的目标。

【讨论】:

  • 谢谢,这确实是 Jeremy 也提到的,我想我会使用 MVC。
【解决方案2】:

我建议阅读观察者模式或 mvc 模式。最好的解决方案可能是 mvc。在 MVC(模型、视图、控制器)中,您将模型(您的数据)保存在视图(两个 jpanel)之外。然后,因为这两个面板共享相同的数据,所以很容易让您的显示面板从您的输入面板驱动。

【讨论】:

  • 更具体地说,您可以将选定的形状保存在 Frame 上的实例变量中(使用 getter 和 setter)。然后,您将“this”(构造 Frame 对象)传递给两个 JPanel 构造函数。然后,您的组合框面板中的控制代码操作 Frame 的形状对象,并且您在形状面板中的显示代码基于 Frame 的形状对象显示。
  • 所以如果我理解正确,对于这种情况,我会有一个单独的模型类,其中包含有关当前形状的信息。然后在 ItemListener 中我会更新这个模型类中的形状,在paintComponent 方法中我会再次从这个模型类中提取形状?那么模型类中的数据会是静态的,还是应该将模型类实例传递给两个面板的构造函数,以便它们持有对它的引用?
猜你喜欢
  • 1970-01-01
  • 2012-05-21
  • 2012-03-12
  • 2011-10-11
  • 2015-03-11
  • 1970-01-01
  • 2014-12-24
  • 1970-01-01
  • 2015-04-20
相关资源
最近更新 更多