使用一个来源的两个 GUI

Using two GUI from one source

我正在处理现有项目,希望对其进行简化并使其可用。我有两个 GUI,我希望他们只从一个资源中获取它们的一些 GUI 代码。我的意思是 gui1.javagui2.java 由它们的 GUI 代码组成。并且,一个用于它们的公共部分。我们称它为 common.java。使用 gui 选择部分,我可以满足选择哪个 gui(gui1 或 gui2)。我想将 common.java 扩展为 JFrame,然后将 gui1.javagui2.java 扩展为 common.java。此外,如果其中一个 GUI 有外部部分,我可以使用 if 条件添加外部部分(正如我所说,我可以确定选择了哪个 gui。)例如:

protected void MovementStateControl() {
        try {
            URL url = new URL(NameofMyproject.GetWepIp() + "<MESSAGE><Command_No>4</Command_No></MESSAGE>");
            URLConnection connection = url.openConnection();
            Document doc = parseXML(connection.getInputStream());
            NodeList Settings = doc.getElementsByTagName("SYSTEM_SETTINGS");
            Node MovementSystem = Settings.item(0);
            Element MovementElem = (Element) MovementSystem;
            jLabel7.setText(MovementElem.getElementsByTagName("device_name").item(0).getTextContent());
            SystemGuiSelect.DeviceName = MovementElem.getElementsByTagName("device_name").item(0).getTextContent();
            NameofMyproject.signal_max_level = Integer.parseInt(MovementElem.getElementsByTagName("signal_max_val").item(0).getTextContent());

            /* If gui1 is selected, the part should be done as well. Otherwise, just above part okay. */
            if (gui1) {
                NameofMyproject.signal_min_level = Integer.parseInt(MovementElem.getElementsByTagName("signal_min_val").item(0).getTextContent());
                if (!"EXISTS".equals(MovementElem.getElementsByTagName("polarization_system").item(0).getTextContent())) {
                    jLabel24.setVisible(false);
                    LblPolAngle.setVisible(false);
                    lblPolTarget.setVisible(false);
                    jLabel13.setVisible(false);
                    jTextField3.setVisible(false);
                    jButton16.setVisible(false);
                    jButton8.setText("Tx-Xy");
                    jButton3.setVisible(false);
                    jButton4.setVisible(false);
                    jProgressBar3.setVisible(false);
                    jLabel36.setVisible(false);
                    jLabel37.setVisible(false);
                    jLabel5.setVisible(false);
                    jButton18.setVisible(false);
                } else {
                    jLabel24.setVisible(true);
                    LblPolAngle.setVisible(true);
                    lblPolTarget.setVisible(true);
                    jLabel13.setVisible(true);
                    jTextField3.setVisible(true);
                    jButton16.setVisible(true);
                    jButton8.setText("Tx-Xy-Zu");
                    jButton3.setVisible(true);
                    jButton4.setVisible(true);
                    jProgressBar3.setVisible(true);
                    jLabel36.setVisible(true);
                    jLabel37.setVisible(true);
                    jLabel5.setVisible(true);
                    jButton18.setVisible(true);
                }
            }

        } catch (Exception e) {  }
    }

这里的问题是我希望将通用 GUI 部分放入 common.java 以消除代码重复,因为两个 GUI 相同的代码太多了。当然因为 common.java 是超 class 它无法知道其子 class 的元素。 (无法识别 JLabel、JButton 等)即使它们的 thread 部分相同,我也无法从同一来源提供它们。 GUI 是使用 NetBeans 创建的。顺便说一下,我的问题解决方案是为所有方法添加参数,但是方法有多少个参数呢? (也许我使用了vargs)但是,我想知道是否有更有效的解决方案。

根据您的方法示例,我建议您使用一个简单的解决方案来解决您的问题。
首先,正如 Gilbert 所建议的那样,公共小部件(文本字段、标签等...)必须位于抽象公共 class 中,并且如果可能的话放在公共 class 中(它更简单)。当然,具体的 gui 的特定小部件将在具体 class 中。 为了简化由具体 classes 操作的通用小部件的使用,请在抽象通用 class.

中声明您的字段受保护

其次,在您的代码段中,您

 if (gui1) { then...

而不是不需要的条件语句(了解 children 家伙不是 parent class 的作用)和繁琐(当时无法维护),我建议你创建监听器。这些将是您的具体 classes 必须实现的简单接口。
当 parent class 分派事件时,它只是简单地分派具体的 classes 采取行动或不采取行动的责任。 为了强制你的具体 classes 实现接口,让你的抽象 class Common 实现这个接口。 这样具体的class就没有实现的选择了

这里有一个非常简单的例子,有两个 GUI 并说明了所提出的概念:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public abstract class CommonFrame extends JFrame implements MyFrameListener {

    protected JLabel myLabelForControlMove;
    private JButton btnControlMove;
    private JPanel panel;

    public CommonFrame() {
        panel = new JPanel();
        add(panel);
        myLabelForControlMove = new JLabel("waiting for information...");
        panel.add(myLabelForControlMove);
        btnControlMove = new JButton("click to control move");
        panel.add(btnControlMove);
        setVisible(true);
        pack();


        // call concrete class with no aware which one is used
        onMovementStateCreation();

        btnControlMove.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
            // call concrete class with no aware which one is used
            onMovementStateControl();
            }
        });
    }
}



public interface MyFrameListener {

  void onMovementStateCreation();

  void onMovementStateControl();

}


public class Gui1 extends CommonFrame {

 @Override
 public void onMovementStateCreation() {
   myLabelForControlMove.setText("control starts");
 }

 @Override
 public void onMovementStateControl() {
   myLabelForControlMove.setText("control with state Gui1");
 }

}


public class Gui2 extends CommonFrame {

  @Override
  public void onMovementStateCreation() {
    myLabelForControlMove.setText("control with state Gui2");
  }

  @Override
  public void onMovementStateControl() {
    // does nothing
  }

}

正如您所提到的,超级 class 不应该知道它的子class。 不要使用 inheritance,而是使用 composition.

common.java应该由其专门的容器组成。这会将 common.javagui1.javagui2.java 中解耦,将来如果您需要添加一个新的 gui3.java,您将不会破坏任何 API,并且只需创建一个新的 SpecializedGUI.java

据我了解,您有 2 个基本问题需要处理。首先是 UI 视图与控制逻辑的分离,其次是增加 Swing 代码中的重用。 我的解决方案是引入一个 In Process Event Bus 用于 View 和 Control 与 Extract Components 使用当前 UI classes 中的通用布局模式,以增加 Swing 代码中的重用。

使用事件总线将视图与控件分离

你需要这个,因为你的观点会有所不同,但你的控制逻辑应该保持不变。您需要找到一种方法来告诉您的 UI device_name 已更改。因此,我建议使用 Event Bus 实现。有一些实现已经为您解决了 EventDispatchThread 处理。

事件总线隔开,你的gui2.java只会对关于它包含的视觉元素的事件和具有所有当前已知字段的 gui1.java 将对所有事件做出反应。您的控制器只是发布事件,而不知道它是被某人消费还是被丢弃。

Etract 组件以增加 Swing 代码中的重用

我建议识别 UI 的公共部分,例如标签组、文本字段等,它们在功能上属于彼此(例如一个人的姓氏和名字)。将它们提取到一个单独的 class 扩展 JPanel 并在任何需要的地方重复使用它们。

不要将这些片段直接注册到 EventBus 或至少注入它们应该响应的事件名称。否则,您不能在一个 JFrame 中使用同一组件的两个实例,因为它们会自动显示相同的值。

我希望这能提供一些想法,从哪里开始重构以及朝着哪个方向发展。