Using two GUI from one source

I'm working on an existing project and am wanted to simplify and make usable it. I have two GUI that I want they to feed from just one resource else their some GUI codes. I mean there are gui1.java and gui2.java consist of their GUI codes. And, one for their common parts. Let's call it as common.java. With gui selection part I can satisfy which gui selected (gui1 or gui2). I think to extend common.java by JFrame then extend gui1.java and gui2.java with common.java. Moreover, If there is external part of one of that GUIs, I can add external part using if condition (as I said I can determine which gui selected.) For example:

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) {  }
    }

The problem is here I want the common GUI parts to put into common.java to remove code duplication because of having two GUI same codes too much. Of course because common.java is super class it cannot be aware of elements of its sub class. (JLabels, JButtons, etc. can't be recognized) Even if their thread parts are same, I can't feed them from same source. The GUIs have been created using NetBeans. By the way, my solution for the problem is adding parameter all methods but what about for the method how many arguments are there? (Maybe I use vargs) however, I wonder whether there are more efficient solution.

Upvotes: 4

Views: 652

Answers (3)

Alexander
Alexander

Reputation: 1421

As far as I understand you have 2 basic problems you need to deal with. First is the separation of UI view from control logic, the Second is to increase the reuse within your Swing code. My solution would be introducing an In Process Event Bus for communication between View and Control and Extract Components with common layout pattern from your current UI classes to increase the reuse within you Swing code.

Separating View from Control using an Event Bus

You need this because your view shall differ, but your control logic shall stay the same. You need to find a way to tell your UI that the device_name has changed. I would suggest to use a Event Bus implementation therefore. There are some realizations that already solve the EventDispatchThread handling for you.

Separated by an Event Bus your gui2.java will only react to the events concerning the visual elements it contains and gui1.java which has all currently known fields will react to all events. Your controller just publishes the events without knowing if it is consumed by someone or just dropped.

Ectract Components to increase reuse within Swing code

I would suggest to identify common parts of the UI, like Groups of labels, textfields and so on, that functionally belong to each other (e.g. Surname and Forename of a person). Extract them to a separate class extending JPanel and reuse them wherever you need it.

Do not register these fragments directly to the EventBus or at least inject the event names they should react to. Otherwise you may not use two instances of the same component within one JFrame because they would automaticallyshow the same values.

I hope this provides some ideas where to start your refactoring and which direction to go.

Upvotes: 3

darthfather
darthfather

Reputation: 377

As you mentioned it, the super class should not know about its subclasses. Instead of using inheritance, use composition.

You common.java should be composed of its specialized containers. This will decoupled common.java from gui1.java and gui2.java, in the future if you require to add a new gui3.java you won't break any APIs and its easy to just create a new SpecializedGUI.java

enter image description here

Upvotes: 2

davidxxx
davidxxx

Reputation: 131326

By basing on your example of method, i propose you to use a simple solution to solve your problem.
First, as Gilbert has suggested, the common widgets (textfield, label, etc...) must be in the abstract common class and if possible layed in the common class (it is more simple). Of course, the specific widgets to a concrete gui will be in the concrete class. To ease the use of common widgets which are manipulated by the concrete classes, declare your fields as protected in your abstract common class.

Second, in your snippet, you do

 if (gui1) { then...

Instead of conditional statements which are not needed (it's not the role of the parent class to know the children guy) and cumbersome (not maintenable in the time) , I propose you to create listeners. These will be simple interfaces that your concrete classes must implement.
It does simply dispatching to the concrete classes the responsibility to act or to no act when a event is dispatched by the parent class. In order to force your concrete classes to implement the interface, make your abstract class Common to implement this interface. In this way, the concrete class will not have the choice to implement it.

Here a very simple example with two guis and illustrating the presented concepts :

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
  }

}

Upvotes: 1

Related Questions