这是 Java 编程的一个领域,文档很少。正如您所提到的,从 JFrame 或 JDialog 扩展来开发 GUI 并不是一个好的设计实践,但是您在示例代码中随处可见。
JSR 296 是一个有用的起点,但它的架构存在一些严重问题。我确实使用 JSR 296,但我有自己的风格,并且必须始终解决框架设计引入的问题。
我一直认为应该有一个讨论组/wiki/专注于这个主题的东西。到目前为止,我发现各种富客户端库的 listserv 很有用,但并不全面。在我的空闲时间可能会考虑开始一些事情:-)
因此,我无法为构建 Swing 应用程序的最佳实践提供任何明确的资源。但是我可以给你一些关于我发现我反复使用的工具包和概念的指导。也许这些对你有用。此外,如果有足够多的人有兴趣就最佳实践、共享代码等进行讨论……我也有兴趣参与其中。
首先,如果您要进行 Swing 开发,一些绝对关键的库:
Binding - 有许多库可以执行此操作(JGoodies、JSR295,它已衍生为一个名为 Better Beans Binding (BBB) 的开源项目、Eclipse 绑定框架)。几年前我开始使用 JGoodies,但我已经转向使用 BBB,因为我发现它的方法更直观。我无法强调绑定所允许的声明式编码方法的优势——它将真正彻底改变您的代码
AppFramework(或其某种形式)- JSR 296 是从这里开始的地方。正如我上面提到的,它有一些问题 - 如果你确实使用 JSR296,我强烈建议你尽量避免使用作为框架核心的单例(除了作为注入框架组件的源之外)你实际上需要)。
编辑 - 自从我写了这篇文章后,我就开始在我们的项目中使用GUTS(这是一个基于 Guice 的应用程序框架 - 它最初是 JSR 296,但几乎没有共同点现在有了它)。 GUTS 仍然是一个年轻的项目,但如果您正在考虑框架,则值得一看。
GlazedLists - 如果你在 UI 中做任何涉及列表、表格或树的事情,你应该仔细看看 GlazedLists。这是一个令人难以置信的项目(不仅适用于 Swing 应用程序,而且它确实在那个领域大放异彩)
验证 - JGoodies 有一个非常好的验证库。学习它,使用它,与它合一。实时验证是现代 Swing 应用程序中极其重要的一部分。
MigLayout - Mig 布局管理器是最好的。我强烈建议不要使用 IDE GUI 构建器的诱惑 - 学习 MigLayout(这将需要几个小时,顶部),并手动编写代码。
所以这些是我书中的关键,绝对必须拥有的图书馆。
现在一些概念:
A.演示模型 - Martin Fowler 有很多关于这种设计模式的信息。总而言之,它将行为与 GUI 级别的表示分开。如果您习惯于 MVC,Presentation Model 会添加另一层分离,这对于“实时”UI 非常重要。我的所有观点都由相应的表示模型支持。最终结果是视图代码非常非常简单 - 专注于两件事:1. 布局,以及 2. 将视图组件绑定到表示模型。就是这样。
B.视图不是 JPanel 的子类。相反,我遵循受 JGoodies 启发的技术,将 View 视为创建 JPanel 的构建器。基本模式是:
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 来构造多个 JPanel,这些 JPanel 都由同一个 PresentationModel 支持 - 由该视图生成的一个面板中的更改将立即在由同一视图生成的另一个面板中可见。
C.使用操作而不是事件处理程序。 JSR 296 实际上在使 Action 易于创建和使用方面做得很好。
D.从 EDT 执行长时间运行的操作(即使是需要 100 毫秒的操作)。 JSR 296 的任务支持使这变得相当容易 - 但是在异常处理方面,296 的任务系统中有许多陷阱。如果您的属性更改又会导致长时间运行的事件,请务必仔细考虑这些更改将发生在哪个线程上。使用 Tasks 对您进行开发的方式有很大的改变,但对于任何真正的 Swing 应用程序来说,它都是一个非常重要的领域——花时间去了解它。
E.资源注入很重要。从一开始就使用它(而不是告诉自己稍后会添加它) - 如果您发现自己在 JLabel 上调用 setText(),那么是时候坐下来调用 setName(),并在资源中添加一个条目文件。如果您有纪律的话,JSR 296 可以让这很容易做到。
我认为现在就足够了 - 这是一个非常复杂的主题,有很多细微差别。在过去的 7 或 8 年里,我一直在努力解决那些不起作用的事情——而且我一直在寻找更好的方法来做那些对我来说很好的事情。