我刚刚开始我的第一个Java Swing项目(之前主要做基于Web的应用程序),并尝试了解如何在MVC组件之间分离关注点的情况下构建正确的体系结构。

我发现的几乎所有文档都非常详细地介绍了每个Swing UI小部件如何工作和如何使用的细节,但是所有示例都只是直接从扩展的Class中调用程序逻辑,例如,JPanel-看起来很奇怪,没有好的建筑。

最好是独立于IDE,但是如果这些事情起作用,应该说在整个项目中,我们已经使用了Eclipse,JFormdesigner和JGoodies。

我还看到JSR296定义了一个似乎可以解决我的问题的框架。我应该只使用实现它的东西吗?

最佳答案

这是Java编程领域中一个文档不足的领域。正如您提到的那样,从JFrame或JDialog扩展到开发GUI并不是一个好的设计实践,但是您可以在示例代码中看到它。

JSR 296是一个有用的起点,但是它的体系结构存在一些严重的问题。我确实使用了JSR 296,但是我有自己的风格,并且始终必须解决框架设计引入的问题。

长期以来,我一直认为应该有一个讨论组/Wiki/针对此主题的内容。到目前为止,我发现各种富客户端库的listserv很有用,但并不全面。在我的空闲时间里,可能需要考虑一些考虑事项:-)

因此,我无法提供任何确定的资源来构建Swing应用程序的最佳实践。但是,我可以为您提供一些指向我发现一遍又一遍的工具箱和概念的指针。也许这些对您很有用。此外,如果有足够的人有兴趣讨论最佳实践,共享代码等,我也有兴趣参与其中。

首先,如果要进行Swing开发,请使用一些绝对关键的库:

  • Binding-有许多库可以做到这一点(JGoodies,JSR295已分解成一个名为Better Beans Binding(BBB),Eclipse绑定(bind)框架的开源项目)。我几年前开始使用JGoodies,但后来我转向使用BBB,因为我发现它的方法更加直观。我不能强调绑定(bind)允许的声明式编码方法的优点-它将彻底改变您的代码
  • AppFramework(或其某些样式)-JSR 296是从此处开始的地方。如上所述,它存在一些问题-如果您确实使用JSR296,我强烈建议您尽量避免使用位于框架核心的单例(而不是作为注入(inject)框架组件的来源)您实际需要的)。

  • 编辑-自从我写这篇文章以来,我就开始在我们的项目中使用GUTS(这是一个基于Guice的应用程序框架-最初以JSR 296开头,但现在几乎没有共同点)。 GUTS仍然是一个年轻的项目,但是如果您考虑使用框架,则值得一看。
  • GlazedLists-如果您正在UI中执行涉及列表,表或树的任何操作,则应仔细查看GlazedLists。这是一个了不起的项目(不仅对于Swing应用程序,而且在那个领域确实很出色)
  • 验证-JGoodies有一个很好的验证库。学习它,使用它,与它合而为一。实时验证是现代Swing应用程序中非常重要的一部分。
  • MigLayout-Mig布局管理器是最好的选择。我强烈建议您不要使用IDE GUI构建器的诱惑-学习MigLayout(这将花费几个小时,最多),并手动编写代码。

  • 因此,这些是我书中关键且绝对必要的库。

    现在一些概念:

    A.演示模型-Martin Fowler对此设计模式有很多了解。总而言之,它将GUI级别的行为与表示分离开来。如果您习惯了MVC,则Presentation Model会添加另一层分离,这对于“实时” UI而言非常重要。我的所有观点都得到了相应的演示模型的支持。最终结果是 View 代码非常非常简单-专注于两件事:1.布局,以及2.将 View 组件绑定(bind)到表示模型。就是这样。

    B. View 不是JPanel的子类。相反,我遵循了JGoodies启发的技术,即将View视为创建JPanels的构建器。基本模式是:
    public class MyView{
      private MyPresentationModel model;
    
      private JButton okButton;
      private JButton cancelButton;
      ...
    
      public MyView(MyPresentationModel model){
        this.model = model;
      }
    
      public JPanel buildView(){
        initComponents(); // this method actually creates the okButton and cancelButton objects
        bindComponentsToModel(); // this method binds those objects to the PresentationModel
        JPanel p = new JPanel(new MigLayout());
        p.add(...);
        ...
        return p;
      }
    }
    

    认真地遵循此方法,可实现易于维护的UI的难以置信的快速开发。请注意,我们可以使用给定的View来构造均由相同PresentationModel支持的多个JPanels-由该 View 生成的一个面板中的更改将立即在由该 View 生成的另一个面板中可见。

    C.使用 Action 而不是事件处理程序。实际上,JSR 296在使Actions易于创建和使用方面做得很好。

    D.在EDT上进行长时间运行的操作(甚至花费100ms的时间)。 JSR 296通过其任务支持使这相当容易-但是,在296的任务系统中,涉及异常处理时有很多陷阱。如果您进行的属性更改又导致长时间运行的事件,请确保仔细考虑这些更改将在哪个线程上发生。使用Tasks是开发方式的重大变化,但是对于任何实际的Swing应用程序来说,这都是一个非常重要的领域-请花一些时间来学习它。

    E.资源注入(inject)很重要。从一开始就使用它(而不是告诉自己以后再添加它)-如果您发现自己在JLabel上调用setText(),现在该坐下来调用setName(),然后在资源中添加一个条目文件。如果您受过纪律约束,那么JSR 296使其非常容易做到。

    我认为目前就足够了-这是一个非常复杂的主题,有很多细微差别。在过去的7或8年中,我一直致力于解决不可行的事情-而且,我还在不断寻找更好的方法来处理对我来说很好的事情。

    09-13 13:22