0

i have a GUI that has 3 menus:Read Files, Add, Finish. under the Add menu specifically, i have 3 menu items called add owner, add residential property and add commercial property. when clicking any of these menu items i have an internal frame come up but i do not want the internal frame to be the same for all menu items. i am trying to add a few more text fields for commercial and residential property compared to owner. so i do not qant the internal frame to be the same but unique for each menu item and that is where i am having trouble. here is the code

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

public class PropertyGUITest
{
    public static void main(String[] args)
    {
        PropertyGUI obj = new PropertyGUI();
        obj.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        obj.setSize(400,300);
        obj.setVisible(true);
        obj.setLocation(100,50);
    }
}

class PropertyGUI extends JFrame
{
    private int countFrames = 0;
    public PropertyGUI()
    {
        super("Property GUI");

        JMenuBar bar = new JMenuBar();
        setJMenuBar(bar);

        JMenu readMenu = new JMenu("Read Files");
        bar.add(readMenu);

        JMenu addMenu = new JMenu("Add");
        bar.add(addMenu);

        JMenuItem newFrame1=new JMenuItem("Add Owner");
        addMenu.add(newFrame1);

        JMenuItem newFrame2=new JMenuItem("Add Residential Property");
        addMenu.add(newFrame2);

        JMenuItem newFrame3=new JMenuItem("Add Commercial Property");
        addMenu.add(newFrame3);

        JMenu finishMenu = new JMenu("Finish");
        bar.add(finishMenu);

        JDesktopPane theDesktop = new JDesktopPane();
        add(theDesktop);

        JMenuItem writeItem = new JMenuItem("Write Owners");
        finishMenu.add(writeItem);

        JMenuItem readpItem = new JMenuItem("Read Properties");
        readMenu.add(readpItem);

        JMenuItem readoItem = new JMenuItem("Read Owners");
        readMenu.add(readoItem);

        JMenuItem exitItem = new JMenuItem("Exit");
        exitItem.addActionListener(
            new ActionListener()
            {
                public void actionPerformed(ActionEvent event)
                {
                    //System.exit(0);
                    dispose();
                }
            }
        );
        finishMenu.add(exitItem);

        newFrame1.addActionListener(
            new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    countFrames++;
                    JInternalFrame jf = new JInternalFrame("Add Owner",true,true,true,true);
                    theDesktop.add(jf);
                    jf.setVisible(true);
                    jf.pack();
                    jf.setSize(300,200);
                    jf.setLocation(countFrames*10,countFrames*20);

                    CustomPanel panel1 = new CustomPanel();
                    jf.add(panel1);


                }
            }
        );

        newFrame2.addActionListener(
            new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    countFrames++;
                    JInternalFrame jf = new JInternalFrame("Add Residential Property",true,true,true,true);
                    theDesktop.add(jf);
                    jf.setVisible(true);
                    jf.pack();
                    jf.setSize(300,200);
                    jf.setLocation(countFrames*10,countFrames*20);

                    CustomPanel panel2 = new CustomPanel();
                    jf.add(panel2);


                }
            }
        );

        newFrame3.addActionListener(
            new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    countFrames++;
                    JInternalFrame jf = new JInternalFrame("Add Commercial Property",true,true,true,true);
                    theDesktop.add(jf);
                    jf.setVisible(true);
                    jf.pack();
                    jf.setSize(300,200);
                    jf.setLocation(countFrames*10,countFrames*20);

                    CustomPanel panel3 = new CustomPanel();
                    jf.add(panel3);


                }
            }
        );
    }

    class CustomPanel extends JPanel
    {
        JTextField tf1;
        JTextField tf2;
        JTextField tf3;
        JTextField tf4;
        JTextField tf5;
        JLabel label1;
        JLabel label2;
        JLabel label3;
        JLabel label4;
        JLabel label5;
        JLabel label6;
        JButton button1;


        public CustomPanel()
        {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weightx = 1;
            gbc.anchor = GridBagConstraints.WEST;
            gbc.insets = new Insets(2, 2, 2, 2);

            add(new JLabel("Name"), gbc);
            gbc.gridy++;
            add(new JLabel("Street"), gbc);
            gbc.gridy++;
            add(new JLabel("City"), gbc);
            gbc.gridy++;
            add(new JLabel("State"), gbc);
            gbc.gridy++;
            add(new JLabel("Zip"), gbc);
            gbc.gridy++;
            add(new JLabel("Submit when done"), gbc);

            JTextField[] fields = new JTextField[5];
            gbc.gridx = 1;
            gbc.gridy = 0;
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            add((fields[0] = new JTextField(10)), gbc);
            gbc.gridy++;
            add((fields[1] = new JTextField(10)), gbc);
            gbc.gridy++;
            add((fields[2] = new JTextField(10)), gbc);
            gbc.gridy++;
            add((fields[3] = new JTextField(10)), gbc);
            gbc.gridy++;
            add((fields[4] = new JTextField(10)), gbc);
            gbc.gridy++;
            JButton btn = new JButton("Submit");
            add(btn, gbc);



        }
    }
}

for commercial and residential property i just want to add two more text fields for account number and price before the submit button.

Student214
  • 29
  • 1
  • 4
  • 10
  • So, I assume that you have a "base" requirement for each frame, from which you need to provide some customisations for each menu? Or are each frame completely different? – MadProgrammer Oct 31 '15 at 00:05
  • yes, each frame is different. the frame that i have coming up is exactly what i need for the add owner menu item but i need it different for the others by adding two more text fields. – Student214 Oct 31 '15 at 00:10
  • So, based on looking at your code, each `ActionListener` is creating it's own `JInternalFrame`, but is adding `CustomPanel` each time, so this would lead me to believe that each `ActionListener` should actually be creating a different component to be added to the `JInternalFrame` instead – MadProgrammer Oct 31 '15 at 00:21
  • What I'm curious about is if any of the other "custom components" you need to create share any common properties. That is does the residential component share any common properties with the commercial property component and does the add own component share any properties with the other, the basic idea is, if you can re-use content then you should – MadProgrammer Oct 31 '15 at 00:22

3 Answers3

1

i do not qant the internal frame to be the same but unique for each menu item and that is where i am having trouble.

CustomPanel panel1 = new CustomPanel();
...
CustomPanel panel2 = new CustomPanel();
...
CustomPanel panel3 = new CustomPanel();

Then you can't use the same panel.

You need 3 different panels. You need:

  1. "OwnerPanel"
  2. "ResidentialPanel"
  3. "CommercialPanel"

Don't try to for the internal frames to use the same panel if the data is different for each panel.

//CustomPanel panel1 = new CustomPanel();
OwnerPanel panel1 = new OwnerPanel();
...
//CustomPanel panel2 = new CustomPanel();
ResidentialPanel panel2 = new ResidentialPanel();
...
//CustomPanel panel3 = new CustomPanel();
CommercialPanel panel3 = new CommercialPanel();
camickr
  • 321,443
  • 19
  • 166
  • 288
  • so the part where i use grid bag layout, i have to specify which panel? – Student214 Oct 31 '15 at 00:16
  • No. You create 3 classes. In each class you use whatever layout you want and you add whatever components you want to the panel. Just copy your CustomPanel 3 times and give it new names and then add/remove compoinents as desired. Each panel will work independently of one another. – camickr Oct 31 '15 at 00:21
1

So, based on your code, each menu item is creating the same component and are adding that to a new JInternalFrame, which obviously, isn't what you want, instead, you want each menu item to create it's own view based on it's needs.

There a few ways you might achieve this, but because the basic mechanism is the same for all of them, you might as well reduce the amount of copy-paste operations you need to do.

First, start by defining the actual views/components you need

public class AddOwnerPane extends JPanel {
    //...
}

public class AddResidentialPropertyPane extends JPanel {
    //...
}

public class AddCommercialPropertyPane extends JPanel {
    //...
}

I was trying to ascertain if there was any common properties which could be shared between the views, but haven't been able to determine that, but if you can, you might subclass from one of the other views or define a "common" view which can be added to the other views, to further reduce your code duplication.

When it comes to this kind of problem, you have two basic chooses, you can either use inheritance, where you define a base class from which all others can extend from...

inheritance

or composition...

Composition

Where the "common" part is (virtually) a stand alone class, but which you make use of within another class.

In GUI's using the inheritance is tricky, as you need to deal with layouts (in particular). This is problematic, as the based classes layout may have very specific requirements, which, if messed with, fall apart really quickly, making it difficult to add new components. The base class probably also has it's own defined life cycle and management expectations, which, again, can make it tricky to incorporate your new requirements

I generally find composition easy to design and manage in these cases.

There are a lot of discussions on the subject, for example:

So, lost of information on the subject, I'll leave to research it further

Next, we need to define a common action, which does most of the heavy lifting

public class ViewAction extends AbstractAction {

    private JDesktopPane desktop;
    private Class<? extends JComponent> view;

    public ViewAction(JDesktopPane desktop, Class<? extends JComponent> view) {
        this.desktop = desktop;
        this.view = view;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        try {
            countFrames++;
            JInternalFrame jf = new JInternalFrame("Add Owner", true, true, true, true);
            JComponent viewComponent = view.newInstance();
            jf.add(viewComponent);
            jf.pack();
            jf.setLocation(countFrames * 10, countFrames * 20);
            jf.setVisible(true);
            desktop.add(jf);
        } catch (InstantiationException | IllegalAccessException ex) {
            ex.printStackTrace();
        }
    }

}

This is basic Action which, when triggered, will create a JInternalFrame, initialise a new instance of the prescribed view, add it to the JInternalFrame and add the JInternalFrame to the desktop pane.

A slightly different approach might have you make this class an abstract class with a abstract method called something like getViewComponent which would be responsible for creating the actual component instead of using Class#newInstance, but what ever works for you.

Next, we define the Actions we need to generate the views we want

public class AddOwnerAction extends ViewAction {

    public AddOwnerAction(JDesktopPane desktopPane) {
        super(desktopPane, AddOwnerPane.class);
        putValue(NAME, "Add Owner");
    }

}

public class AddResidentialPropertyAction extends ViewAction {

    public AddResidentialPropertyAction(JDesktopPane desktopPane) {
        super(desktopPane, AddResidentialPropertyPane.class);
        putValue(NAME, "Add Residential Property");
    }

}

public class AddCommercialPropertyAction extends ViewAction {

    public AddCommercialPropertyAction(JDesktopPane desktopPane) {
        super(desktopPane, AddCommercialPropertyPane.class);
        putValue(NAME, "Add Commercial Property");
    }

}

Each of these Actions extends from ViewAction and simply provides the required Class reference to the view component that the Action will create and sets up there individual properties.

And finally, we create the JMenuItems for each of the actions...

addMenu.add(new JMenuItem(new AddOwnerAction(theDesktop)));
addMenu.add(new JMenuItem(new AddResidentialPropertyAction(theDesktop)));
addMenu.add(new JMenuItem(new AddCommercialPropertyAction(theDesktop)));

Basically, we defined a series of self contained units of work, which reduces the amount of code duplication you might otherwise have needed simply to add a different view component for each action

Have a look at How to Use Actions for more details

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

Since the panel for customer and residental property share the some common components, you can add a subclass of CustomerPanel for commercial and residential properties.

This requires some refactoring of the CustomerPanel so that most of its code is reusable. For example, a setUpBaseLayout() to add the common components, a setUpCustomizedLayout() to add the additional components that commercial and residential Panel can extend, a setUpSubmitButton() which comes after the first two methods to add the submit button.

class CustomPanel extends JPanel {
    JTextField tf1;
    JTextField tf2;
    JTextField tf3;
    JTextField tf4;
    JTextField tf5;
    JLabel label1;
    JLabel label2;
    JLabel label3;
    JLabel label4;
    JLabel label5;
    JLabel label6;
    JButton button1;
    GridBagConstraints gbc = new GridBagConstraints();

    public void setUpBaseLayout() {
        setLayout(new GridBagLayout());

        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(2, 2, 2, 2);

        add(new JLabel("Name"), gbc);
        gbc.gridy++;
        add(new JLabel("Street"), gbc);
        gbc.gridy++;
        add(new JLabel("City"), gbc);
        gbc.gridy++;
        add(new JLabel("State"), gbc);
        gbc.gridy++;
        add(new JLabel("Zip"), gbc);

        JTextField[] fields = new JTextField[5];
        gbc.gridx = 1;
        gbc.gridy = 0;
        gbc.weightx = 1;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        add((fields[0] = new JTextField(10)), gbc);
        gbc.gridy++;
        add((fields[1] = new JTextField(10)), gbc);
        gbc.gridy++;
        add((fields[2] = new JTextField(10)), gbc);
        gbc.gridy++;
        add((fields[3] = new JTextField(10)), gbc);
        gbc.gridy++;
        add((fields[4] = new JTextField(10)), gbc);

    }

    public void setUpCustomizedLayout() {

    }

    public CustomPanel() {
        setUpBaseLayout();
        setUpCustomizedLayout();
        setUpSubmitButton();
    }

    private void setUpSubmitButton() {
        gbc.gridx = 0;
        gbc.gridy++;
        add(new JLabel("Submit when done"), gbc);

        gbc.gridx = 1;
        JButton btn = new JButton("Submit");
        add(btn, gbc);
    }
}

class ResidentialPanel extends CustomPanel {
    ResidentialPanel() {
        super();
    }

    public void setUpCustomizedLayout() {
        gbc.gridx = 0;
        gbc.gridy++;
        add(new JLabel("Account Number"), gbc);

        gbc.gridy++;
        add(new JLabel("Price"), gbc);


        gbc.gridx = 1;
        gbc.gridy--;
        add(new JTextField(10), gbc);

        gbc.gridy++;
        add(new JTextField(10), gbc);
    }
}

So for residential frame, you can use:

  CustomPanel panel2 = new ResidentialPanel();
                    jf.add(panel2);
Bon
  • 3,073
  • 5
  • 21
  • 40