你最好的 Swing 设计模式和技巧是啥? [关闭]
Posted
技术标签:
【中文标题】你最好的 Swing 设计模式和技巧是啥? [关闭]【英文标题】:What are your best Swing design patterns and tips? [closed]你最好的 Swing 设计模式和技巧是什么? [关闭] 【发布时间】:2010-10-04 12:26:36 【问题描述】:我正在使用 Swing 为应用程序编写 GUI,为了代码维护和可读性,我希望在整个系统中遵循一致的模式。
我读过的大部分文章和书籍(或至少书籍部分)似乎都提供了大量关于如何创建和排列各种组件的示例,但忽略了编写完整 GUI 的大局。
您对应用程序 GUI 设计的最佳建议是什么?在设计或重构 GUI 应用程序时您遵循哪些模式?
【问题讨论】:
这是我的四个孩子:blue-walrus.com/swing-design-patterns 【参考方案1】: Karsten Lentzsch 的 JGoodies 对我的架构设计非常有帮助,尤其是在表示模型模式、绑定和验证方面。查看他的articles 和libraries。 使用类似 MVC 的模式。我说“喜欢”是因为目标实际上是将视图与模型分开,而不是符合 MVC 的特定风格。我更喜欢自己使用Presentation Model。 MiGLayout - 除非有基本的布局管理器,否则我会使用它。 尽可能模块化和重用。 WindowBuilder Pro for Eclipse - 最好的视觉设计师,因为它可以与现有/编辑的代码一起使用,并且不会锁定你。而且它现在是免费的!我对使用设计器没有意见,因为视图应该与其他代码分开。 Netbeans Platform (RCP) - 唯一真正的 Swing 框架。我希望在有时间的时候学习和使用它,因为框架的一部分工作就是解决像您这样的问题。 JavaBuilders - 允许声明式 UI 的酷项目,但我不确定它是否成熟到可以冒险,尤其是在现有项目中。不过,阅读他们的 PDF 书籍是为了了解他们试图解决的问题,这很有趣。【讨论】:
【参考方案2】:大量使用 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)并继续重复使用它们。
【讨论】:
【参考方案3】:我认为并发的良好工作知识通常被低估了。您确实需要熟悉 Swing 的线程策略和通用同步技术才能构建响应式 GUI 和高效的后端。
【讨论】:
【参考方案4】:我认为您将面临的主要问题是您的 gui 应用程序的可测试性。
因此,关于可维护性和单元测试的易用性,我倾向于“Presenter first”习惯用语,而不是模型视图控制器 (MVC) 和其他指示您让视图了解实际应用程序逻辑 (模型) 的派生词。最好的资源是引入它的小组的web site。
由于使用这样的方法需要大量样板代码来初始化应用程序的各种元素,我还建议使用依赖注入框架。我已经和Guice达成和解了。
【讨论】:
【参考方案5】:避免在用户多次单击操作按钮时产生过多线程。在第一次单击时禁用按钮,在后台线程中生成您的操作,完成后,再次启用按钮。对于短期运行的任务,这可能不是问题。
【讨论】:
【参考方案6】:当组合更容易时避免继承。
例如我见过很多这样的:
public class CustomerSupportApp extends JFrame
JList<Customer> customers;
OtherBusinessComponent importantComponent;
etc. etc
这是将业务逻辑与表示混合在一起。它只会使改变从困难变为不可能。
更好的是:
public class CustomerSupportApp
JList<Customer> customers;
OtherBusinessComponent importantComponent;
// The app HAS-A frame but not IS-A frame
JFrame frame;
etc. etc
【讨论】:
在您的情况下很明显,因为 application != frame,但还有其他示例,例如FooFrame extends BarFrame
,继承也不合适,例如因为他们的共同点太少了。【参考方案7】:
您不应该扩展 JFrame、JDialog、JPanel、JButton、Janything 类(尽管某些对表行为的扩展只有在扩展时才可用)。如果您想做自定义组件,可以扩展 JComponent。如果应该实现模型(例如通过扩展抽象模型)、侦听器(例如通过扩展适配器),仅此而已。您通常不需要/必须扩展 swing 组件,最好不要这样做,因为它会使您的代码与超类的实现相关联。
【讨论】:
【参考方案8】:永远不要从 JDialog、JFrame 或 JInternalFrame 派生来定义您的表单、对话框...
而是从 JPanel 派生而来。这将为您带来以下优势:
以后可以从 例如,JFrame 到 JDialog (因为用户改变了主意) 您可以将一个面板实例从一个 JDialog 重用到另一个(JDialog 通常不可重用,因为它们是通过对其“父级”、框架或另一个对话框的引用来构建的) 您可以稍后更改替换 JDialog具有更多功能 来自第 3 方框架的子类。【讨论】:
除此之外,我还要定义一个“视图”界面。 你的“视图”界面应该做什么?【参考方案9】:这是关于你的 GUI 代表什么的更抽象的高级答案,而不是它的机制..
根据您的任务,制作它可能有点困难,因此您的用户可以从概念上掌握 GUI 正在做什么。我已经完成了一些涉及 GUI 的非常棘手的工作,我最成功的方法是采用一组复杂的控件并将它们放入用户期望的布局中。
例如,我编写了一个系统来管理 T1 线路两端的 2 个设备(有点像调制解调器)。控件真的很难理解——诸如“创建环回、测试远端信号、测试近端位模式、发送各种位模式……”(这是一个巨大的过度简化,比这更糟糕)
我必须真正了解这个问题,所以我去找了一位技术支持代表,他一直在帮助客户解决这个问题。他向我展示了手册中的图表,并引导我了解了不同控件在该图表上的作用。
我拿了这个图,用图形重新创建了它(大部分只是一个简单的线图,但它显示了两端和它们之间的连接),然后使用图形的区域来表示控件和反馈(颜色变化)。您可以直观地看到信号正在发出。当您在远端打开环回时,您可以看到线路将信号循环回其输出线路,然后您可以看到颜色发生变化,因为您的近端开始获得它正在发送的模式,它是另一条线路.
“控件”比这复杂得多,但 GUI 将其简化为客户理解问题所需的确切内容。
在此之后,我们有客户回来告诉我们,他们以前从未能够解决这个问题,但现在他们完全明白了!
这个演示比 GUI 实现的布线重要得多。
【讨论】:
【参考方案10】:查看应用程序框架 API(https://appframework.dev.java.net/ 和 http://java.sun.com/developer/technicalArticles/javase/swingappfr/。这是构建您的摇摆应用程序的绝佳 API。例如:所有样式(颜色、字体、图标...)都在一个简单的配置文件。
【讨论】:
【参考方案11】:尽量不要将文本编码到您的应用中。 Swing gui 可以很容易地编写为数据驱动,考虑在 xml 文件中定义您的 GUI(包括组件名称和位置/布局属性)。
我在具有大量属性表的系统上工作(它们只是一堆控件,一页又一页)——如果不使其成为数据驱动的,几乎不可能维护或国际化。
如果您决定使用 GUI 构建器,请不要修改它输出的代码(如果可以避免的话)——最好从外部类绑定到 GUI。想想如果你不得不在没有构建器的情况下做会发生什么——移植会很困难吗?不可能?
了解 Swing 中的陷阱——仅从 AWT 线程修改 GUI 组件,尽快返回 AWT 线程(如果您必须执行任何超过 100 毫秒的操作,则生成一个新线程),
尽最大努力保持代码干燥——使用 Swing GUI 可能是一个真正的编程挑战——再一次,数据驱动代码是我发现的唯一方法,而不是不断重复代码 新的 JButton("...");
如果您的数据是基于属性表的,请认真考虑创建一种绑定机制来将您的控件与数据联系起来。 DRY 代码的一个好的目标是每个控件使用 0(零)行特定于控件的代码,以便从数据库中获取一条数据到 GUI,让用户对其进行编辑并将其返回到您的数据库中。这意味着您应该能够通过修改数据来添加新控件。
【讨论】:
【参考方案12】:绝对将GUI放在一个类中,将逻辑放在另一个类或多个类中——尽可能地。如果您使用MVC (Model-View-Controller) 模式,这将自动发生。如果不这样做,GUI 将很快变得复杂到难以维护。
【讨论】:
【参考方案13】:养成让你的回调产生线程来完成实际工作的习惯,这样当你的一个回调变成一个耗时的怪物时,你就不会出现冻结的 GUI。
【讨论】:
是的,SwingWorker 是产生线程的众多方法之一。 如果该线程之后需要更新 GUI,请不要忘记 SwingUtilities 调用程序 :) 看看 FoxTrot:foxtrot.sourceforge.net【参考方案14】:mvc 是你的朋友。
【讨论】:
【参考方案15】:避免使用 GUI 布局设计器(构建器)。稍后它将使您的代码更清晰,更易于维护。
【讨论】:
确实,如果您使用构建器启动 GUI,那么您几乎致力于在 GUI 的整个生命周期中使用该构建器。这有时是可以接受的,有时不是。 是的,这是真的。不同的构建器以不相互兼容的不同格式存储元数据。唯一的例外是直接使用代码的 Instantiations Swing Designer。他们都创建了不能手动编辑的代码(不可读),以后会咬你。 我不同意。如果您对 Swing 非常了解,那么由 GUI 构建器生成的任何代码都将具有足够的可读性。问题是,通过使用 GUI 构建器,您将无法很好地了解 Swing。良好的分离当然是必要的。 WindowBuilder Pro 在生成代码方面做得很好。看看:developers.google.com/java-dev-tools/wbpro/?hl=fr【参考方案16】:使用布局管理器。您可能认为现在用硬编码位置定位所有内容更简单(特别是如果您使用图形布局工具),但是当需要更新 gui 或将其国际化时,您的继任者会讨厌您。 (相信我,我是从一开始就说要使用布局管理器的人,也是忽略我的人的继任者。)
【讨论】:
以上是关于你最好的 Swing 设计模式和技巧是啥? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
java中,swing设计中,为啥JOptionPane.showmessageDialog()弹出对话框后,单击确定按钮能关闭窗口?