0

I am using a self made toolbar to navigate through my application and the toolbar is present on all pages. Each time a new page is displayed I am closing the current frame and opening a new one, using the following code:

java.awt.Window win[] = java.awt.Window.getWindows(); 
for(int i=0;i<win.length;i++){ 
win[i].dispose(); 
}

I am doing it this way as the ActionListeners are declared in the toolbar class, whilst the frames for each page are declared at runtime and are not static.

This all works fine except for one particular case-the "cancel" button, where the first time the frame is accessed it will close once. The second time it will close and re open 2 times, the third 3 and so on. I have tracked this using the "counter" in the code.

I have minimised the code to recreate the same behaviour, as below:

Toolbar Class

 public class Toolbar {

    static JButton buttonCancel = new JButton("Cancel");
    static int counter;

    public static JPanel Toolbar(String panelname){

        FlowLayout layout = new FlowLayout();

        JPanel Toolbar = new JPanel(new BorderLayout());
        Toolbar.setLayout(layout);

        GridLayout GLayout = new GridLayout(2,1);
        GLayout.setVgap(0);

        JPanel container2 = new JPanel();

        if(panelname.matches("Customers")){

        container2.setLayout(GLayout);
        JButton buttonAddCust = new JButton("Add Cust");
        container2.add(buttonAddCust, BorderLayout.PAGE_START);

        buttonAddCust.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                java.awt.Window win[] = java.awt.Window.getWindows(); 
                for(int i=0;i<win.length;i++){ 
                win[i].dispose(); 
                }

             Customers.AddCustomersGui();           
            }
        });
        }


        JPanel container21 = new JPanel();
        if(panelname.matches("Add Customers")){ 
            container21.setLayout(GLayout);
            container21.add(buttonCancel, BorderLayout.PAGE_START);

            buttonCancel.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {

                    counter ++;                 
                    java.awt.Window win[] = java.awt.Window.getWindows(); 
                    for(int i=0;i<win.length;i++){ 
                    win[i].dispose(); 
                    }                       
                    System.out.println("Coutner " + counter);                   
                    Customers.CustomersGui();   

                }
                });
        }

        Toolbar.add(container2);      
        Toolbar.add(container21);

        return Toolbar;

    }



}

GUI class

public class Customers extends Toolbar{

    public static void CustomersGui(){

        final JFrame frame = new JFrame("Customers");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel customers = new JPanel();

        customers.add(Toolbar.Toolbar(frame.getTitle()));

        frame.setContentPane(customers);

        frame.setSize(1200,500);

        frame.setVisible(true);

    }

    public static void AddCustomersGui(){

        final JFrame frame1 = new JFrame("Add Customers");
        frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel Addcustomers = new JPanel();

        Addcustomers.add(Toolbar.Toolbar(frame1.getTitle()));

        frame1.setContentPane(Addcustomers);

        frame1.setSize(1200,500);

        frame1.setVisible(true);
    }
    }

main class

public static void main(String[] args) {

    Customers.CustomersGui();

}
Am_I_Helpful
  • 18,735
  • 7
  • 49
  • 73
  • You must be re-adding a listener somewhere – Hovercraft Full Of Eels Oct 31 '14 at 14:51
  • 1
    `"Each time a new page is displayed I am closing the current frame and opening a new one."` -- a better design is probably not to swap windows which can be annoying, but rather to swap JPanel views using a CardLayout. Please read [The Use of Multiple JFrames, Good/Bad Practice?](http://stackoverflow.com/questions/9554636/the-use-of-multiple-jframes-good-bad-practice). – Hovercraft Full Of Eels Oct 31 '14 at 14:53
  • @Alex- Why are you removing all your questions??? Any problem??? – Am_I_Helpful Dec 13 '14 at 12:08
  • @shekharsuman yes because of the behaviour of the people on this community. Quite frankly it is bullying and I do not want any part of it –  Dec 13 '14 at 12:44

1 Answers1

2

You are adding a new ActionListener to the buttonCancel, with each iteration of your code and this is the reason for your program's behavior.


Also, as per my comment, you state,

Each time a new page is displayed I am closing the current frame and opening a new one.

A better design is probably not to swap windows which can be annoying, but rather to swap JPanel views using a CardLayout. Please read The Use of Multiple JFrames, Good/Bad Practice?.


For example, add this line of code to your program:

  if (panelname.matches("Add Customers")) {
     container21.setLayout(GLayout);
     container21.add(buttonCancel, BorderLayout.PAGE_START);
     buttonCancel.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
           counter++;
           java.awt.Window win[] = java.awt.Window.getWindows();
           for (int i = 0; i < win.length; i++) {
              win[i].dispose();
           }
           System.out.println("Coutner " + counter);
           Customers.CustomersGui();
        }
     });

     // ***** add this here **********
     System.out.println("buttonCancel ActionListener count: "
           + buttonCancel.getListeners(ActionListener.class).length);
  }

and you'll see that the ActionListeners get added multiple times to this button.


An example of swapping views:

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

@SuppressWarnings("serial")
public class SwapPanels extends JPanel {
   public static final String CUSTOMER = "customer";
   public static final String ADD_CUSTOMER = "Add Customer";
   protected static final int PREF_W = 800;
   protected static final int PREF_H = 600;
   public static final String CANCEL = "Cancel";
   private CardLayout cardLayout = new CardLayout();

   public SwapPanels() {
      setLayout(cardLayout);

      add(createCustomerPanel(CUSTOMER), CUSTOMER);
      add(createAddCustomerPanel(ADD_CUSTOMER), ADD_CUSTOMER);
   }

   public void showCard(String key) {
      cardLayout.show(this, key);
   }

   public JPanel createAddCustomerPanel(String name) {
      JPanel addCustPanel = new JPanel() {
         @Override
         public Dimension getPreferredSize() {
            if (isPreferredSizeSet()) {
               return super.getPreferredSize();
            }
            return new Dimension(PREF_W, PREF_H);
         }
      };
      addCustPanel.setName(name);
      addCustPanel.setBorder(BorderFactory.createTitledBorder(name));
      addCustPanel.add(new JButton(new AbstractAction(CANCEL) {
         {
            int mnemonic = (int)getValue(NAME).toString().charAt(0);
            putValue(MNEMONIC_KEY, mnemonic);
         }

         @Override
         public void actionPerformed(ActionEvent e) {
            if (CANCEL.equals(e.getActionCommand())) {
               SwapPanels.this.showCard(CUSTOMER);
            }
         }
      }));
      return addCustPanel;
   }

   private JPanel createCustomerPanel(String name) {
      JPanel custPanel = new JPanel() {
         @Override
         public Dimension getPreferredSize() {
            if (isPreferredSizeSet()) {
               return super.getPreferredSize();
            }
            return new Dimension(PREF_W, PREF_H);
         }
      };
      custPanel.setName(name);
      custPanel.setBorder(BorderFactory.createTitledBorder(name));
      custPanel.add(new JButton(new AbstractAction(ADD_CUSTOMER) {
         {
            int mnemonic = (int)getValue(NAME).toString().charAt(0);
            putValue(MNEMONIC_KEY, mnemonic);
         }

         @Override
         public void actionPerformed(ActionEvent e) {
            if (ADD_CUSTOMER.equals(e.getActionCommand())) {
               SwapPanels.this.showCard(ADD_CUSTOMER);
            }
         }
      }));
      return custPanel;
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("SwapPanels");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new SwapPanels());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
Community
  • 1
  • 1
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • if that is the case then why is it only happening for one case when an identical situation occurs with the button buttonAddCust but it does not have the same problem? –  Oct 31 '14 at 15:02
  • @jim: because you create a new JButton for the add cust but you don't for the cancel, and so the same button gets the listener added multiple times. – Hovercraft Full Of Eels Oct 31 '14 at 15:11