我正在使用Swing为应用程序编写GUI,为了代码维护和可读性,我希望在整个系统中遵循一致的模式。
我读过的大多数文章和书籍(或至少是书籍部分)似乎提供了大量关于如何创建和安排各种组件的示例,但忽略了编写完整GUI的大局。
有关应用程序GUI设计的最佳技巧是什么,以及在设计或重构GUI应用程序时您遵循哪些模式?
答案 0 :(得分:19)
永远不要从JDialog,JFrame或JInternalFrame派生来定义表单,对话框......
取而代之的是JPanel。这将带给您以下优势:
答案 1 :(得分:15)
使用布局管理器。您可能认为现在使用硬编码位置定位所有内容更简单(特别是如果您使用图形布局工具),但是当需要更新gui或将其国际化时,您的继任者会讨厌您。 (相信我,我就是那个从一开始就使用布局管理器的人,以及那个不理我的人的继任者。)
答案 2 :(得分:14)
避免使用GUI布局设计器(构建器)。稍后它将使您的代码更清晰,更易于维护。
答案 3 :(得分:9)
我认为并发的良好工作知识经常被低估。您确实需要熟悉Swing的线程策略和一般同步技术,以构建响应式GUI和高效的后端。
答案 4 :(得分:8)
mvc是你的朋友。
答案 5 :(得分:8)
这是一个关于GUI代表什么的更抽象的高级答案,而不是它的机制......
根据您的任务,可能很难做到这一点,因此您的用户可以在概念上掌握GUI正在做什么。我做了一些涉及GUI的非常棘手的工作,而我最成功的方法是采用一组复杂的控件并将它们放入用户期望的布局中。
例如,我写了一个系统来管理T1线路两端的2个设备(有点像调制解调器)。这些控件真的难以理解 - 像“创建环回,测试远端信号,测试近端位模式,发送各种位模式,......”等字段(这是一个非常过于简单化,它比这更糟糕)
我必须真正理解这个问题,所以我去了一位技术支持代表,他一直帮助客户解决这个问题。他向我展示了手册中的图表,并指导我完成了不同控件在该图表上的操作。
我拿图表,使用图形重新创建它(大部分只是一个简单的线条图,但它显示了两端和它们之间的连接),然后使用图形区域来表示控件和反馈(颜色变化)。您可以直观地看到信号已经消失。当您在远端打开环回时,您可以看到该线将信号循环回到它的输出线,然后您可以看到颜色变化,因为您的近端开始获得它发送出来的模式的另一条线
“控件”比这更复杂,但GUI将其简化为客户理解问题所需的内容。
在此之后,我们让客户回到我们面前告诉我们他们以前从未能够弄清楚这些东西,但现在他们完全得到了它!
这个演示文稿比GUI实现的连接更加重要。
答案 6 :(得分:8)
当用户多次单击操作按钮时,避免产生太多线程。首次单击时禁用按钮,在后台线程中生成操作,完成后再次启用按钮。对于短期运行任务而言,这可能不是问题。
答案 7 :(得分:7)
养成让你的回调产生线程来做实际工作的习惯,然后当你的一个回调变成一个耗时的怪物时,你就不会有冻结的GUI。
答案 8 :(得分: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
}
答案 9 :(得分:6)
大量使用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)并继续重用它们。
答案 10 :(得分:6)
答案 11 :(得分:5)
尽量不要将文字编码到您的应用中。 Swing guis可以非常容易地编写为数据驱动,考虑在xml文件中定义GUI(包括组件名称和位置/布局属性)。
我处理的系统有很多属性表(只是成堆的控件,一页又一页) - 没有数据驱动,几乎不可能维护或国际化。
如果你决定使用GUI构建器,如果你可以避免它,就不要修改它输出的代码 - 最好从外部类绑定到GUI。想想如果你必须在没有建造者的情况下做到这一点将会发生什么 - 是否难以移植?不可能?
了解摇摆中的陷阱 - 只修改AWT线程中的GUI组件,尽快返回AWT线程(如果你需要做超过100ms的任何事情,则生成一个新线程),
尽量保持代码干净 - 使用Swing GUI可能是一个真正的编程挑战 - 同样,数据驱动代码是我发现不能不断重复代码的唯一方法 新的JButton(“......”);
如果您的数据是基于属性表的,请认真考虑创建绑定机制以将控件绑定到您的数据。 DRY代码的一个好目标是每个控件的0(ZERO)特定于控件的代码行,以便从数据库到GUI获取一段数据,让用户编辑它并将其返回到数据库。这意味着除了修改数据外,您应该能够添加新控件。
答案 12 :(得分:4)
绝对将GUI放在一个类中,将逻辑放在另一个类或多个类中 - 尽可能。如果您使用MVC (Model-View-Controller)模式,则会自动执行此操作。如果不这样做,GUI很快就会变得难以维护。
答案 13 :(得分:4)
您不应该扩展JFrame,JDialog,JPanel,JButton,Janything类(尽管表格行为的某些扩展仅在您扩展时才可用)。如果您想要自定义组件,可以扩展JComponent。如果应该实现模型(例如通过扩展抽象模型),监听器(例如通过扩展适配器),但就是这样。您通常不需要/不得不扩展swing组件,最好不要这样做,因为它会使您的代码与超类的实现相关联。
答案 14 :(得分:3)
查看应用程序框架API(https://appframework.dev.java.net/和http://java.sun.com/developer/technicalArticles/javase/swingappfr/。它是构建swing应用程序的绝佳API。例如:所有样式(颜色,字体,图标......)都是在一个简单的配置文件中定义。
答案 15 :(得分:1)