-1

I have a Main window (JFrame) which contains many components including a button. The button, when pressed, opens another Window (JFrame), let's call it customers window, for the user to search details and present those details back in the Main window.

There are many windows similar to the Main window and all those main windows have their own customers window for searching and presenting the details.

Now, my question is I want to have only 1 class of the customers window for all main windows instead of having it for each main window. This is because everything inside the customers window is same for all the main windows, except each customers window open the details for that specific main window i.e. set texts for fields and insert data into table and so on.. The problem here is when I have to modify something... I have to code all the rest of the customers window as well which is time wasting and also increases the size of the application/repeated code..

So, I would like know of some way that I could have 1 class of customers window for all the main windows and keep track of the main window which opens the customers window so I can open the details in that main window. Please note that user will open multiple main windows at the same time and thus, require opening multiple instances of customers window.

Below is some code to give an idea of how I am doing it currently...

Cash_sale_customer_window:

..... get all the data from database.....

CashSaleInvoice.customerNumberTextField.setText(rs.getString(1));
CashSaleInvoice.customerNameTextField.setText(rs.getString(2));
....and so on....

Credit_sale_customer_window:

.....get all the data from database.....

CreditSaleInvoice.customerNumberTextField.setText(rs.getString(1));
CreditSaleInvoice.customerNameTextField.setText(rs.getString(2));
....and so on....

Screenshot of the program:

Main Window: http://postimg.org/image/adrdmrli5/

Cash Sale Invoice: http://postimg.org/image/6bcdynwhd/

Any help will be greatly appreciated!

HMH
  • 33
  • 6

2 Answers2

2

First of all, take a look at at The Use of Multiple JFrames: Good or Bad Practice?

Second, consider using modal dialogs instead, as these will allow you "pause" the execution of the code at the point the dialog is made visible and "continue" execution after it is closed.

This allows you to prompt the user for details, collect the results and process them without need to set up a chain of references or callbacks

Take a look at How to make dialogs for more details

Updated

If you can't use a modal dialog, then you need to pass a reference of the main frame to the child frames. Personally, I would start by defining an interface which describe the permissible actions that the child frames can perform against the main window, this way you decouple the implementation and prevent the child frames from doing things to the main window that they shouldn't, like removing all the components...

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thank you for your input. I have already looked at the link you provided.. That's the problem.. I do not want hold the entire application if some dialog is opened unless it is informational/warning or asking question, in that case I have used JDialogs and JOptionPanes.. please check the links for screenshots of the program that I have added now. – HMH Aug 05 '14 at 21:54
  • Sorry, but I think you misunderstood my question. The thing I am looking for is in @ryvantage answer but I just can't seem to figure out how can I open the frame I already have. Could you please have a look there? – HMH Aug 06 '14 at 11:58
1

I might be misreading the question, but I've done something like this in the past. Here's the code I've written. It's a Singleton, Duplicatable JFrame (I extend a JPanel for reasons specific to my design).

How this works: If you try to open a new window and it is already open, it receives focuse. If it is not, it opens a new window. It uses an identifier variable (which could be anything) to keep track.

How to use it: Use the static showPanel method so that the class determines whether you need a new panel or not, like this:

SingletonDuplicatableFramePanel.showPanel(new SingletonDuplicatableFramePanel(identifier));

(remember, SingletonDuplicatableFramePanel is abstract, so you'll need to make another class that extends it).

You pass showPanel() a new instance of your class.

  • If it needs the new instance, it uses it.
  • If it doesn't need the new instance, it throws it away (NOTE: constructors of the new instances should do practically nothing because they might not be needed).

The abstract method init() is only executed if the new instance is actually created. This is where you initialize whatever you need for the new window. At the end of your init() method, you call setVisible().

As mentioned earlier, to make it duplicatable, it keeps track of a unique identifier which it uses to determine if you already have an instance open or not. It should be clear when you run the demo.

Here's the code for the SingletonDuplicatableFramePanel:

public abstract class SingletonDuplicatableFramePanel extends JPanel {

   public SingletonDuplicatableFramePanel(String name) {
       this.name = name;
   }
   static LinkedHashMap<Class, LinkedHashMap<Object, SingletonDuplicatableFramePanel>> self_panel_map;

   JFrame self_jf;
   protected SingletonDuplicatableFramePanel self_panel;
   boolean loading;
   boolean showing;
   LinkedList<SingletonDuplicatableFramePanel> vpanel_children;
   LinkedList<JDialog> dialog_children;

   public final String name;
   public abstract void init();

   private boolean searchablePanel;

   public boolean isSearchablePanel() {
       return searchablePanel;
   }

   public void setSearchablePanel(boolean searchablePanel) {
       this.searchablePanel = searchablePanel;
   }

   public void toFront() {
       self_jf.toFront();
   }

   protected Object identifier;
   public static SingletonDuplicatableFramePanel showPanel(Object identifier, SingletonDuplicatableFramePanel newInstance) {
       if(self_panel_map == null)
           self_panel_map = new LinkedHashMap<>();
       Class newInstanceClass = newInstance.getClass();
       if(self_panel_map.containsKey(newInstanceClass) && self_panel_map.get(newInstanceClass).containsKey(identifier)) {
           SingletonDuplicatableFramePanel oldInstance = self_panel_map.get(newInstanceClass).get(identifier);
           oldInstance.showing = oldInstance.self_jf.isVisible();

           if(!oldInstance.loading && !oldInstance.showing) {
               newInstance.loading = true;
               newInstance.self_panel = newInstance;
               newInstance.self_jf = new JFrame(newInstance.name);
               newInstance.identifier = identifier;
               newInstance.self_panel.init();
               self_panel_map.get(newInstanceClass).put(identifier, newInstance);
               return newInstance;
           } else if(oldInstance.showing) {
               oldInstance.self_jf.toFront();
           }
           return oldInstance;
       } else {
           if(!self_panel_map.containsKey(newInstanceClass))
               self_panel_map.put(newInstanceClass, new LinkedHashMap<Object, SingletonDuplicatableFramePanel>());
           newInstance.loading = true;
           newInstance.self_panel = newInstance;
           newInstance.self_jf = new JFrame(newInstance.name);
           newInstance.identifier = identifier;
           newInstance.self_panel.init();
           self_panel_map.get(newInstanceClass).put(identifier, newInstance);
           return newInstance;
       }
   }

   public void addChild(SingletonDuplicatableFramePanel panel) {
       if(vpanel_children == null)
           vpanel_children = new LinkedList<>();
       vpanel_children.add(panel);
   }

   public void dispose() {
       loading = false;
       showing = false;
       self_jf.dispose();
   }

   boolean packed;
   public void pack() {

       self_jf.add(self_panel);
       self_jf.pack();
       self_jf.addWindowListener(new WindowAdapter() {
           @Override
           public void windowClosing(WindowEvent e) {
               if(vpanel_children != null)
                   for(SingletonDuplicatableFramePanel vpanel : vpanel_children)
                       vpanel.dispose();
               if(dialog_children != null)
                   for(JDialog dialog : dialog_children)
                       dialog.dispose();
           }
       });
       setLocationByPlatform(true);
       self_jf.toFront();
       self_jf.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
       packed = true;
   }

   public void setVisible() {
       if(!packed) {
           pack();
       }
       self_jf.setVisible(true);
       loading = false;
   }

   public void setTitle(String title) {
       self_jf.setTitle(title);
   }

   public void centerJF() {
       self_jf.setLocationRelativeTo(null);
   }

   public void setLocationByPlatform(boolean bool) {
       self_jf.setLocationByPlatform(bool);
   }

}

And here's a sample of it in use:

static class My_SDFP extends SingletonDuplicatableFramePanel {

    String customer_number;
    public My_SDFP(String customer_number) {
        super("My SDFP");
        this.customer_number = customer_number;
    }

    @Override
    public void init() {
        JLabel label = new JLabel("Customer Number = " + customer_number);
        add(label);
        setVisible();
    }

}

public static void main(String[] args) {

    JFrame baseFrame = new JFrame();
    baseFrame.setLayout(new GridBagLayout());
    JButton button = new JButton("Open customer #");
    final JTextField identifier_field = new JTextField();
    button.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent evt) {
            String identifier = identifier_field.getText();
            My_SDFP.showPanel(identifier, new My_SDFP(identifier));
        }
    });
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.insets = new Insets(2, 2, 2, 2);
    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;

    gbc.gridy = 1;
    baseFrame.add(new JLabel("Customer #:"), gbc);
    baseFrame.add(identifier_field, gbc);

    gbc.gridwidth = 2;
    gbc.gridy = 2;
    baseFrame.add(button, gbc);
    baseFrame.pack();
    baseFrame.setLocationByPlatform(true);
    baseFrame.setVisible(true);
    baseFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

Type a number in the Customer # field and click the button. You'll notice that you can't open two instances of the same customer number. If you try, it only refocuses the frame you're trying to re-open (but can't because it's already open).

enter image description here

Community
  • 1
  • 1
ryvantage
  • 13,064
  • 15
  • 63
  • 112
  • Wow.. I will need some time to digest all that and check if it works for me and will let you know asap.. thank you for your effort! – HMH Aug 05 '14 at 22:48
  • Could you please explain a little more on how can i open my own Jframes that I already have? – HMH Aug 07 '14 at 17:54