Java Swing 的一般问题

7
我制作了一个Swing应用程序,功能相对简单。然而,它所包含的代码变得非常庞杂且混乱。所有Swing组件和操作都在一个文件中。因此,如果我要制作更大的应用程序并添加更多功能,那么代码将会很难阅读。
我的问题是如何构建良好的代码结构。或者是否有一些好的网页可以阅读,并提供一些代码示例。我已经查看了Sun关于Swing的教程,但这些示例相对较为简单。
更新:我思考了一段时间并查看了一些示例。我不知道我是否正确地理解了MVC模式。无论如何,我的想法是将每个JFrame分别放到它们自己的类文件中。然后我有一个MainFrame,它是应用程序的主窗口。从那个JFrame中,我创建了我拥有的每个JFrame的一个实例。并通过操作从MainFrame调用那些frame。我不知道这是否是一个好主意。但是这使得代码显著易于阅读。
以下是我所说的示例:
class Main implements ActionListener {

    private JFrame frame = new JFrame();
    private JButton button1 = new JButton();
    private JPanel panel = new JPanel();

    private FirstFrame frame1 = new FirstFrame();
    private SecondFrame frame2 = new SecondFrame();
    private ThirdFrame frame3 = new ThirdFrame();

    public Main() {
        button1.addActionListener(this);
    }

    public createGUI() {
        frame.setTitle("Main");
        frame.setSize(400,300);
        panel.add(button);

        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
    }

    public static void main(String args[]) {
        new Main().createGUI();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == button1)
        {
            frame1.enable();
        }
    }
}

1
太棒了!我已经思考了一段时间了。 - Steve De Caux
4个回答

8

使用模型-视图-控制器设计模式。它处理将用户界面代码与业务逻辑分离。

编辑:

由于OP需要有组织的代码而不是灵活的设计,因此我已从答案中删除了NetBeans UI Designer部分。


我曾经在Eclipse中使用过可视化UI插件,但我的经验是它会添加很多无用的代码。Netbeans也是这种情况吗? - starcorn
然而,如果有资源可以阅读的话,我也喜欢手动学习编程。 - starcorn

5
组织大型用户界面代码是一个问题,但关于此问题的写作却很少,尽管每个应用程序都存在这个问题。以下是一些可行的技术:
1. 重构 - 清理代码混乱。 2. 模型视图控制器模式 - 分离关注点。 3. 面向对象设计 - 使用许多小的、相互合作的类,而不是大块的代码。 4. “在事件上执行操作” - 将动作与视图分离的惯用语。 5. UML组件模型 - 可视化类级别以上的设计概念。 6. 依赖反转原则 - 组织代码依赖。
基本的设计技术已经存在了很长时间,并且被广泛理解,但将这些技术应用到更大规模的应用程序中似乎需要为每个应用程序单独设计。
我见过的一种有效方法是将事件、监听器、动作等分离到它们自己的类中,然后按类型将它们组织成包,或者跨包使用一致的命名约定,以便能够轻松识别组件及其关联类(XDialog、XDialogMouseListener、XDialogCancelAction等)。
另一种方法是查看一些大型开源应用程序(如Eclipse、Firefox等),看看它们如何组织其GUI代码。

如何分离代码?由于我有一些视图依赖于操作,因此我无法将其分离。 - starcorn
如果您将一个操作从视图中分离出来,但它不再编译,则可以引入额外的方法,以允许单独的类访问缺失的功能。这些额外的方法应该组织成接口。如果这些方法不应该公开使用,则可以使用包级别访问声明接口。 - richj
在MVC中,视图通常不依赖于操作,尽管在MV2中,视图和控制器可以更紧密地耦合。引入接口允许您使用依赖反转原则来反转任何错误方向的依赖关系。 - richj

2

我倾向于尽可能地将与GUI无关的功能从Swing组件中分离出来。这意味着您需要一些额外的间接性。但是:

  1. Swing层仅处理GUI交互
  2. 业务功能更容易测试,因此更易于维护

我并不一定在谈论完整的MVC模型(虽然那也不错)。这更像是一个类/包组织问题。


对于实用主义者来说,我也是这样做的。特别是在使用GUI设计器(如JFormDesigner)时,它使添加按钮等操作和操作处理程序变得非常容易。将所有这些内容放在单个类中,并调用辅助类是有意义的。例如,我的打印操作只是一个包装器,它调用new PrintTask().print(myJob)。PrintTask是一个独立的(非内部)类,与GUI无关。 - Sam Barnum

1

需要记在脑海中的是,UI编程和其他类型的编程一样。不要认为它很特别,可以忽略合理实践。不幸的是,大多数教程代码都很糟糕,而生产中的代码可能会更糟糕。

关键点:

  • 使用分层设计。这不仅仅是持久性-业务-UI。将其细分。例如,布局层不应该创建组件(除了用于布局的JPanel之外)。
  • 偏向组合而非继承。几乎没有必要对JFrameJPanel等进行子类化,所以不要这样做。
  • 保持UI的轻量级。例如,渲染器中应该有很少的逻辑。首先这使得测试更容易(这是自动化测试,手动大规模测试是适得其反的)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接