我正在为使用Swing的应用程序编写GUI,为了维护代码和可读性,我希望在整个系统中遵循一致的模式。什么是你最好的Swing设计模式和技巧?
我读过的大部分文章和书籍(或者至少是书本章节)似乎都提供了大量有关如何创建和安排各种组件的示例,但忽略了编写完整GUI的大图。
什么是应用程序GUI设计的最佳提示,以及在设计或重构GUI应用程序时遵循哪些模式?
我正在为使用Swing的应用程序编写GUI,为了维护代码和可读性,我希望在整个系统中遵循一致的模式。什么是你最好的Swing设计模式和技巧?
我读过的大部分文章和书籍(或者至少是书本章节)似乎都提供了大量有关如何创建和安排各种组件的示例,但忽略了编写完整GUI的大图。
什么是应用程序GUI设计的最佳提示,以及在设计或重构GUI应用程序时遵循哪些模式?
使用布局管理器。你可能会认为只需要用硬编码的位置来定位所有的东西就更简单了(特别是如果你使用图形化布局工具的话),但是当需要更新gui或者国际化时,你的后继者会恨你。 (请相信我,我是一开始就使用布局管理器的人,以及忽视我的人的继任者。)
避免使用GUI布局设计器(构建器)。稍后它会让你的代码更清洁和更容易维护。
确实,如果你用一个建造者开始你的GUI,你几乎承诺整个使用这个建造者GUI的整个生命周期。这有时可以接受,有时不可以。 – Eddie 2009-01-30 17:27:01
是的,这是真的。不同的构建者以不相互兼容的不同格式存储元数据。唯一的例外是Instantiations Swing Designer,它直接与代码一起工作。 所有这些代码都不会被手动编辑(无法读取),这会稍后再咬你。 – Marko 2009-01-30 17:30:23
我不同意。如果您知道Swing,那么由GUI构建器生成的任何代码都将具有足够的可读性。问题在于,通过使用GUI构建器,您无法很好地了解Swing。良好的分离当然是必要的。 – willcodejavaforfood 2009-02-01 14:49:47
mvc是你的朋友。
养成你的回调产生线程来完成实际工作的习惯,然后当你的回调变成一个耗时的怪物时,你不会有冻结的GUI。
绝对把GUI放在一个类中,而把逻辑放在另一个类或多个类中 - 尽最大可能。如果您使用MVC (Model-View-Controller)模式,则会自动发生。如果你不这样做,GUI将很快变得难以维系复杂。
尽量不要将文本编码到您的应用程序中。 Swing guis可以很容易地写成数据驱动,可以考虑在xml文件中定义你的GUI(包括组件名称和位置/布局属性)。
我工作的系统有很多属性表(它们只是一堆一堆的控件,一页接一页地) - 如果没有数据驱动,几乎不可能维护或国际化。
如果您决定使用GUI构建器,请不要修改它输出的代码(如果可以避免的话) - 最好从外部类绑定到GUI。想想如果你必须在没有建造者的情况下做到这一点会发生什么 - 难以移植吗?不可能?
理解挥杆的陷阱 - 只能从AWT线程修改GUI组件,尽可能迅速返回AWT线程(生成一个新的线程,如果你做任何事情,需要大于100ms),
尝试最好让代码保持干爽 - 这可能是Swing GUI的一个真正的编程挑战 - 同样,数据驱动的代码是我发现的不会重复代码的唯一方式,如 新的JButton(“...”) ;
如果您的数据基于属性表,请认真考虑创建绑定机制以将控件与数据绑定。对于DRY代码来说,一个好的目标是每个控件的控制特定的代码行,以便从数据库中获取一段数据到您的GUI,并让用户编辑它并将其返回到数据库。这意味着你应该可以通过不做任何事情来修改你的数据来添加一个新的控件。
这是一个更抽象的关于GUI代表什么的高层次的答案,而不是它的机制。
根据任务的不同,它可能是一种很难说这样你的用户可以在概念上把握什么GUI正在做什么。我已经做了一些非常棘手的工作,涉及GUI,我最成功的方法是将一组复杂的控件放入用户期望的布局中。
例如我写了一个系统来管理2台设备的一个在T1线路(有点像调制解调器)的任一端。这些控件真的很难理解 - 像“创建回送,测试远端信号,测试近端位模式,发送各种位模式......”(这是一个巨大的过度简化,比这更糟糕)
我必须真正理解这个问题,所以我去了一位技术支持代表,他帮助客户解决了这个问题。他向我展示了手册中的图表,并向我介绍了该图表上不同的控件。我用图形重新创建了它(大部分只是一个简单的线条图,但它显示了两端和它们之间的连接),然后使用图形区域来表示控件和反馈(颜色变化)。你可以通过视觉看到信号正在传出。当你在远端打开一个环回时,你可以看到这条线路将信号环回到它的外线,然后你可以看到颜色的变化,因为你的近端开始得到它发出它的另一条线路的模式。
“控件”比这个显著比较绕口,但是GUI也减少到需要什么客户来理解问题。
在此之后,我们有客户回来给我们告诉我们,他们从未能够前算出这个东西出来,但现在他们完全得到它!
此演示文稿比GUI实现的布线更为重要。
查看应用程序框架API(和http://java.sun.com/developer/technicalArticles/javase/swingappfr/)。这是一个非常棒的API来构建您的swing应用程序,例如:所有样式(颜色,字体,图标...)都在一个简单的配置文件中定义。 。
切勿的JDialog,JFrame的或派生的JInternalFrame定义你的表格,对话框...
从JPanel的派生而这将带给您follwing优点:
您不应该扩展JFrame,JDialog,JPanel,JButton,Janything类(尽管表行为的某些扩展只在扩展时才可用)。如果您想做自定义组件,可以扩展JComponent。如果应该实现模型(例如通过扩展抽象模型),听众(例如通过扩展适配器),但就是这样。通常不需要/不得不扩展摆动组件,而且最好不要这样做,因为它使您的代码与超类的实现相关联。
构图更容易时避免继承。
比如我见过像这样的很多:
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
}
避免生成当用户点击操作按钮多次线程太多。在第一次点击时禁用按钮,在后台线程中产生动作,完成后再次启用按钮。这对短期运行任务可能不是问题。
我认为并行的一个良好的工作知识往往是低估。您确实需要熟悉Swing的线程策略和常规同步技术,才能构建响应式GUI和高效的后端。
大量使用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)并继续重用它们。
这里是我的四个孩子:http://blue-walrus.com/swing-design-patterns/ – 2013-07-02 07:30:31