如何构建一个Swing应用程序

8
我对Swing或GUI设计没有太多经验(包括大学时期的几个WPF应用程序),但我被要求重构工作中的一部分Swing遗留应用程序。我需要重构的部分涉及一个弹出窗口,它可以根据某个值对象以三种不同的格式显示。这三种不同的格式都共享一些基本字段,并根据条件确定额外的字段。负责此GUI元素的类约有5k长,我认为应该将其拆分为三个子类,其中包含它们都扩展的共享内容的基类。但是我完全不知道这是否是正确的方法。
有人能否介绍一些处理共享元素(如按钮/字段等)的不同Swing组件的策略?
另外,有没有可以用来学习的大型开源Swing应用程序?
更多信息:我正在处理的应用程序是一个庞大的遗留应用程序,目前结构非常可怕。我是团队中的新成员(并且是最近的毕业生,因此在这方面没有太多经验),被要求尝试将目前负责此弹出窗口显示的一个巨大类拆分为更小、更易于维护的组件。本质上,应用程序中有一个弹出窗口,允许用户响应某些事件,并根据所需响应的请求的子类型有三个不同的外观。大部分GUI元素在所有三种子类型中都是一致的,因此我想知道继承是否是这里最好的方法,或者是否有其他处理此问题的策略?

3
这是一个很好的问题,但用几段话回答比较困难。通常,将GUI分解成需要定义GUI所需的JPanels数量,并为每个JPanel创建一个Java类。在定义Swing组件时使用组合。只有在覆盖JComponent中的方法时才使用继承。 - Gilbert Le Blanc
@joey 抱歉如果我表现得像个白痴 - 如何使用它?目前,大类需要一个参数p,根据此参数的子类型,将某些视图元素添加到面板中。约50%的元素始终显示,无论传递的参数如何。我的最初想法是将公共字段留在主类中,然后有三个子类来存储特定类型的内容。但这可能是个可怕的想法,我也不确定! - rhbrb
@GilbertLeBlanc 感谢您的回复,我已经开始将所有内容分解为基于面板的小类。一如既往,我尽可能地倾向于组合而非继承,但是您对处理共享组件有什么建议吗?例如,共享按钮或文本字段等组件的面板,但也具有某些附加字段? - rhbrb
目前所有的东西都在一个类中,所以如果我想要拥有具有相同功能的按钮,我必须在面板A和面板B之间复制代码?您建议在面板A中创建按钮A,在面板B中创建按钮B,然后从其他地方共享它们的操作吗? - rhbrb
1
@OhButYouWillPets 即使具有相同的功能,也要为每个面板或窗体制作不同的按钮。如果您对Swing不太了解,请先学习它,事情会变得清晰明了。 - joey rohan
显示剩余4条评论
2个回答

20

根据评论,我认为我可以回答这个问题。一个真正的答案需要一本书来解释。

  1. 将您的GUI拆分为尽可能多的嵌套的JPanel以描述您的GUI。一个简单的使用BorderLayout的嵌套的JPanel优于使用GridBagLayout的复杂的JPanel。请注意,我并不是批评GridBagLayout。在创建表单时很有用。但它不是唯一的Swing布局管理器。

  2. 将每个嵌套的JPanel放入其自己的类中。

  3. 在使用Swing组件时,请使用组合。仅在您的类将重写其中一个JComponent方法时才使用继承。

  4. 每个JPanel都有其自己的JButtonJLabel等组件。即使GUI的用户认为它们是相同的按钮,也必须为JPanel A定义JButton A,并为JPanel B定义JButton B。您可以通过创建包含标签和按钮文本的GUI模型来最小化重复。您必须通过编写通用的ActionListener来消除操作代码(按钮按下时执行的代码),以使JButton A和JButton B可以执行。

  5. Swing应用程序必须从调用SwingUtilities.invokelater()开始。这确保了Swing组件在事件分派线程(EDT)上定义和使用。

  6. 一个Swing应用程序只使用一个 JFrame

  7. 每个JPanel必须定义一个Swing布局管理器。

  • 某些组件,如JListJTable,在被包含在JScrollPane中时可以更好地工作。

  • 我相信我可能还忘记了一些东西,但这应该是一个很好的开始。


    1
    非常感谢你的帮助,Gilbert。这对我来说是一个很好的起点。 - rhbrb
    1
    非常好的回答!您会为唯一的JFrame推荐什么名称? - sexyboy
    2
    如果项目中使用了Gui功能,需要在主窗口(Frame)中添加相应的元素,并使用统一的命名规则。同时需要为项目取一个与Gui有关的名称。 - piegames

    2
    如果您设置一个抽象类来创建50%的共享代码,然后从中扩展呢?
    例如:
    abstract class BasePopupPanel extends JPanel {
    
        public void initialize() {
            // Initialize all the shared code here.
            // eg. add(new JButton("TEST");
        }
    }
    

    现在您可以创建实际的弹出式面板:

    public class GiraffePopupPanel extends BasePopupPanel {
    
        public void initialize() {
            super.initialize();
            // Here you do all the initializations for this class.
        }
    }
    

    您可以创建任意数量的这些内容。当需要添加它们时...

    ...假设您有一个名为displayPopup的方法,那么签名看起来应该像这样:

    public void displayPopup(BasePopupPanel popup) {
        // do stuff regarding JDialogs, etc.
        // ...
        popup.initialize();
        // do more stuff...
    }
    

    我希望这能为您提供一种重构类的方法。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接