我正在为使用Swing的应用程序编写GUI,为了代码维护和可读性,我希望在整个系统中遵循一致的模式.
我读过的大多数文章和书籍(或至少是书籍部分)似乎提供了大量关于如何创建和安排各种组件的示例,但忽略了编写完整GUI的大局.
有关应用程序GUI设计的最佳技巧是什么?在设计或重构GUI应用程序时,您遵循哪些模式?
永远不要从JDialog,JFrame或JInternalFrame派生来定义表单,对话框......
而是来自JPanel.这将带给您以下优势:
稍后可能会从JFrame更改为JDialog(因为用户改变了主意)
你可以重用一个JDialog中的一个面板实例到另一个面板实例(JDialog通常不可重复使用,因为它们是通过引用它们的"父",框架或另一个对话框构建的)
您可以稍后使用来自第三方框架的更实用的子类替换JDialog.
使用布局管理器.您可能认为现在使用硬编码位置定位所有内容更简单(特别是如果您使用图形布局工具),但是当需要更新gui或将其国际化时,您的继任者会讨厌您.(相信我,我是那个从一开始就使用布局管理器的人,以及那个不理我的人的继任者.)
避免使用GUI布局设计器(构建器).稍后它将使您的代码更清晰,更易于维护.
我认为对并发的良好工作知识经常被低估.您确实需要熟悉Swing的线程策略和一般同步技术,以构建响应式GUI和高效的后端.
mvc是你的朋友.
这是一个关于GUI代表什么的更抽象的高级答案,而不是它的机制.
根据您的任务,可能很难做到这一点,因此您的用户可以在概念上掌握GUI正在做什么.我做了一些涉及GUI的非常棘手的工作,我最成功的方法是采用一组复杂的控件并将它们放入用户期望的布局中.
例如,我写了一个系统来管理T1线路两端的两个设备(有点像调制解调器).这些控件真的难以理解 - 像"创建环回,测试远端信号,测试近端位模式,发送各种位模式,......"等字段(这是一个非常过于简单化,它比这更糟糕)
我必须真正了解这个问题,所以我去了一个技术支持代表谁帮助客户解决这个问题所有的时间.他给我看一个图的手册中,走到我通过什么不同的控制做到了图上.
我把该图中,用图形它重新创建的(只是一个简单的画线的大部分,但它显示出两端和它们之间的连接),则图形的然后使用区域来表示的控制和反馈(颜色变化) .您可以直观地看到信号已经消失.当你打开一个环回在远端,你可以看到线环的信号返回到它的输出线,那么你可以看到颜色的变化为您的近端开始得到它被发送出的图案它的其他线路.
"控件"比这更复杂,但GUI将其简化为客户需要了解的问题.
在此之后,我们让客户回到我们面前告诉我们他们以前从来没有能够弄清楚这些东西,但现在他们完全得到了它!
此演示文稿比GUI实现的连接更加重要.
当用户多次单击操作按钮时,避免产生太多线程.首次单击时禁用按钮,在后台线程中生成操作,完成后再次启用按钮.这对于短期运行任务可能不是问题.
养成让你的回调产生线程来做实际工作的习惯,然后当你的一个回调变成一个耗时的怪物时,你就不会有冻结的GUI.
当组合更容易时,避免继承.
例如,我看到很多像这样:
public class CustomerSupportApp extends JFrame { JListcustomers; OtherBusinessComponent importantComponent; etc. etc }
这是将业务逻辑与表示混合在一起.它只能从困难变为不可能.
更好的是:
public class CustomerSupportApp { JListcustomers; OtherBusinessComponent importantComponent; // The app HAS-A frame but not IS-A frame JFrame frame; etc. etc }
大量使用MVC模式.这是我的意思的一个简单例子:
class Person { String firstName; String lastName; // and getters and setters... } class PersonSwingModel { private Person person; private javax.swing.text.PlainDocument firstName; private javax.swing.text.PlainDocument lastName; // and getters and setters... // Create some method like init() that initializes PlainDocument values // to attributes in model. } class SavePersonAction extends AbstractAction { private PersonSwingModel model; // and getters and setters... } class PersonSwingView extends JFrame { private PersonSwingModel model; private javax.swing.JTextField firstName; private javax.swing.JTextField lastName; private SavePersonAction savePersonAction; // hook up to JButton/JMenuItem // and getters and setters... // Create some method like init() which binds PlainDocument to JTextField // and Actions to JButtons or JMenuItems }
我看到有些人不同意扩展JFrame或JPanel.我不.适合我.
另外,使用LayoutManagers.GridBagLayout功能非常强大.如果使用它,请定义一些GridBagConstraints常量(如LABEL_GBC和FIELD_GBC)并继续重用它们.
Karsten Lentzsch的JGoodies对我的建筑设计非常有帮助,特别是在Presentation Model模式,绑定和验证方面.看看他的文章和图书馆.
使用类似MVC的模式.我说"喜欢",因为目标实际上是将视图与模型分开,而不是符合MVC的特定风格.我更喜欢自己使用Presentation Model.
MiGLayout - 我将它用于一切,除非基本的布局管理器会这样做.
尽可能模块化和重用.
WindowBuilder Pro for Eclipse - 最好的视觉设计师,因为它适用于现有/编辑过的代码并且不会锁定你.它现在是免费的!我对使用设计器没有任何问题,因为视图应该与其余代码分开.
Netbeans平台(RCP) - 唯一真正的Swing框架.我希望在有空的时候学习并使用它,因为框架的一部分工作是解决像你这样的问题.
JavaBuilders - 允许声明性UI的酷项目,但我不确定它是否足够成熟以冒险,特别是对于现有项目.然而,阅读他们的PDF书籍只是为了理解他们试图解决的问题是有趣的.
尽量不要将文本编码到您的应用中.Swing guis可以非常容易地编写为数据驱动,考虑在xml文件中定义GUI(包括组件名称和位置/布局属性).
我研究的系统有很多属性表(只是成堆的控件,一页一页) - 没有数据驱动,几乎不可能维护或国际化.
如果您决定使用GUI构建器,则永远不要修改它输出的代码(如果您可以避免它) - 最好从外部类绑定到GUI.想想如果你必须在没有建造者的情况下做到这一点将会发生什么 - 是否难以移植?不可能?
了解摇摆中的问题 - 只修改AWT线程中的GUI组件,尽快返回AWT线程(如果你需要做超过100毫秒的任何事情,则产生一个新线程),
尽量保持代码干燥 - 使用Swing GUI可能是一个真正的编程挑战 - 同样,数据驱动代码是我发现不能像新JButton("...")那样不断重复代码的唯一方法;
如果您的数据是基于属性表的,请认真考虑创建绑定机制以将控件绑定到您的数据.DRY代码的一个好目标是每个控件的0(ZERO)特定于控件的代码行,以便从数据库到GUI获取一段数据,让用户编辑它并将其返回到数据库.这意味着您应该能够通过不做任何事情来修改数据来添加新控件.