5

我的问题归结为:Swing 编程中的标准结构是让听众控制新组件(例如新的 JPanel)以进行显示和输入,并让新组件的听众控制新组件以进行显示和输入,等等到无穷大?或者 Java 是否需要恢复为某种统一类,将所有 Swing 组件按程序顺序联系在一起?

目前,在我的仅使用一个 JFrame 的应用程序中,在我的侦听器中,我的初始 JFrame 对象作为参数传递给我的所有 JPanel,因此他们的侦听器可以调用 removeall() 来清除新 JPanel 的框架。例如短代码如下

public class MainFrame {
  JFrame jfrm;
  public MainFrame() {
    jfrm = new JFrame("Main Frame");
    JPanel mainPanel = new MainPanel(jfrm);
  }
}

public class MainPanel extends JPanel {
  public MainPanel(final JFrame mainFrame) {
    JButton example = new JButton("Example");
    example.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent le) {
            mainFrame.removeall();
            JPanel 2ndPanel = new 2ndPanel(mainFrame);
            mainFrame.add(2ndPanel);
            mainFrame.validate();
        }
    });
  }
}

这是正确的结构吗?生成新面板的是听众而不是某个统一的类?但是如果是这样的话,如果有无限的级联监听器,Java 的编译器怎么会到达 mainFrame.validate() 呢?我是一名老派程序程序员,试图用 Java 编写 Swing 应用程序,我想我可能没有掌握 Swing 编程的基本概念。期待任何有用的答案,并提前致谢!

4

4 回答 4

4

我不会那样做的。观察者模式在Swing 中用于发送通知,通常作为用户操作的结果。

举个例子:用户“点击”按钮是因为他想要在 MainFrame 中创建一个新面板。但是按钮不知道单击该做什么。他所能做的就是通知事件侦听器,它已被选中。

所以我们需要一些对通知感兴趣的组件。该组件可以向按钮注册一个监听器并接收通知。侦听器是其他组件的“耳朵”(或“眼睛”)。但是耳朵(或眼睛)不会采取行动。它只是其他组件传感器。

这让我们回到了主要问题:想要被告知,如果按钮被点击,必须采取行动。这是一个主要的设计问题。创建面板并将其添加到主框架的绝对不是侦听器。它可以是创建和添加子面板的主框架角色,也可以是负责创建带有子面板的框架的第三个组件的角色。

但是对于这段代码来说,listner 是一个糟糕的地方。

于 2010-08-19T11:26:04.630 回答
3

您可能希望查看隐藏/显示它们,而不是破坏和创建面板。有一个 CardLayout 布局管理器可以做到这一点:http: //journals.ecs.soton.ac.uk/java/tutorial/ui/layout/card.html

基本上,这个想法是在程序开始时构建并添加所有面板,然后使用布局管理器在视图之间切换。

正如其他人所说,您可能希望在您的设计中添加某种模型,该模型负责维护系统的状态。

于 2010-08-19T11:35:34.530 回答
1

首先,您不应该让侦听器直接操纵框架,使用嵌套JPanel或它的ContentPane.

您的问题取决于您的听众所在的位置。您应该只JFrame从类本身向 a 添加组件。在你的情况下没关系,因为逻辑仅限于类本身。

我不认为有无限的听众。它们在一个列表中并按顺序执行。您的侦听器应该SwingUtilities.invokeLater用于操纵主框架。

我发现JFrame作为参数的传递有点多余。为什么不从构造函数外部创建侦听器?

 final JPanel mainPanel = new MainPanel();     
 JButton example = new JButton("Example");
 example.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent le) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
               MainFrame.this.removeAll();
               MainFrame.this.add(mainPanel);
            }
         });;
    }
 });
 add(example);

这不是最好的例子,但我注意到你正在尝试做什么。

底线是您应该在侦听器之外创建组件,然后使用侦听器添加它。

于 2010-08-19T11:31:16.493 回答
1

您组织代码的方式并不罕见,因此有些混乱。作为 Java 的一般规则,不要在没有理由的地方进行子类化。JPanel子类化or很少有意义JFrame

将组件分配给创建它们的类中的字段也很少有意义。事实上,在构造函数中做的更少。

在匿名内部类中做的也更少。解开事件数据并调用对封闭类有意义的方法作为操作。

于 2010-08-19T19:25:18.590 回答