更新时间:2023-01-13 14:55:22
我不是 GUI 构建器的忠实粉丝:他们通常会自动生成大量代码,然后将整个开发团队锁定为使用一个 IDE.另外,这段代码经常不可读(查看Netbeans下使用Matisse时生成的代码).
I'm not a big fan of GUI builders: They typically autogenerate bucket-loads of code that then locks in your whole development team to using one IDE. Also, this code is often unreadable (check the code generated when using Matisse under Netbeans).
我对 GUI 设计/调试的建议是:
My recommendations for GUI design / debugging would be:
main
方法,允许其他开发人员轻松确定组件的外观.Action
而不是 ActionListener
并将这些动作注册到每个 JComponent
的 ActionMap
.这允许它们被提取"并添加到 UI 的其他部分(例如 JToolBar
),同时它们的状态仍然由拥有"JComponent
控制(即松散耦合).assert SwingUtilities.isEventDispatchThread()
.TaskManager
类,该类注册到我的 UI 状态栏.任何后台处理(在SwingWorker
s 内执行)都被传递到由TaskManager
创建的Task
的句柄.与任务交互(通过调用 setDescription(String)
、setThrowable(Throwable)
、cancel()
)会导致更新状态栏.它还导致为全局"任务显示玻璃窗格……但这与单个 SwingWorkers 完全分离/隐藏.Observer
/Observable
类,而是使用 ChangeListener
、PropertyChangeListener
或您自己的自定义用于传播事件的侦听器实现.Observer
传递一个 Object
作为它的事件,强制客户端代码使用 instanceof 检查类型并执行向下转换,使代码不可读并使类之间的关系不太清楚.JTable
而不是 JList
,即使在您的表只有一列的情况下.JList
在其 API 中有一些令人讨厌的功能,包括您需要为其提供原型值才能正确计算其大小.DefaultTableModel
,因为它通常会导致您将模型"数据存储在两个位置:在您的实际业务对象中以及 DefaultTableModel
所在的二维数组中在.相反,只需将 AbstractTableModel
子类化 - 这样做非常容易,这意味着您的实现可以简单地委托给数据结构(例如 List
)存储您的数据.main
method to each panel (or "top-level" component) implementation, allowing other developers to easily determine what a component looks like.Action
s over ActionListener
s and register these actions with each JComponent
's ActionMap
. This allows them to be "extracted" and added to other parts of the UI (e.g. JToolBar
) whilst still having their state controlled by the "owning" JComponent
(i.e. loose coupling).assert SwingUtilities.isEventDispatchThread()
.TaskManager
class that is registered with my UI's status bar. Any background processing (performed within SwingWorker
s) is passed a handle to a Task
created by the TaskManager
. Interracting with the Task (by calling setDescription(String)
, setThrowable(Throwable)
, cancel()
) causes the status bar to be updated. It also causes the glass pane to be displayed for "global" tasks ... but this is all decoupled / hidden from the individual SwingWorkers.Observer
/ Observable
classes, but instead favour ChangeListener
, PropertyChangeListener
or your own custom listener implementation for propagating events. Observer
passes an Object
as it's event, forcing client code to check the type using instanceof and to perform downcasts, making code unreadable and making relationships between classes less clear.JTable
over JList
, even in situations where your table only has one column. JList
has some nasty features in its API including the fact that you need to provide a prototype value for it to calculate its size correctly.DefaultTableModel
as it typically results in you storing your "model" data in two places: In your actual business objects and also within the 2D array that DefaultTableModel
sits on. Instead, simply subclass AbstractTableModel
- It's very easy to do this and means your implementation can simply delegate through to the data structure (e.g. List
) storing your data.