I have an application which is much more complicated than this, but this simplified code has the same issue. The full application has 4 tabs in a tabbed pane and queries a database to update tables within scroll panes. As each search for information is requested the listeners fire more than once per request, causing the application to slow down to the point of being unusable.
The following minimized code demonstrates the problem. There is a button on each tab which has a listener attached. The buttons are "pressed" alternatively...tab 0, tab 1, tab 0, tab 1, etc. The system output shows how the multiplication propagates. Iterations #1 & 2 are fine...the listeners are fired once each. Iterations 3 through 6 show each listener firing twice although the buttons were pressed once each time. Iterations 7 through 14 then show each listener firing 4 times. It's obvious that this doubling each time is drastically slowing down the application by querying the database multiple times for the same information.
System output:
Iteration #1 Tab 0 listener alerted
Iteration #2 Tab 1 listener alerted
Iteration #3 Tab 0 listener alerted
Iteration #4 Tab 0 listener alerted
Iteration #5 Tab 1 listener alerted
Iteration #6 Tab 1 listener alerted
Iteration #7 Tab 0 listener alerted
Iteration #8 Tab 0 listener alerted
Iteration #9 Tab 0 listener alerted
Iteration #10 Tab 0 listener alerted
Iteration #11 Tab 1 listener alerted
Iteration #12 Tab 1 listener alerted
Iteration #13 Tab 1 listener alerted
Iteration #14 Tab 1 listener alerted
Here's the code:
package SwingTest;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class SwingTest extends JFrame
{JTabbedPane MainScreen = new JTabbedPane();
final static long serialVersionUID = 1L;
int iter = 0;
JPanel tab0Panel = new JPanel();`your text`
final JLabel t0ID = new JLabel("Tab 0");
JButton t0Test = new JButton("Test");
JPanel tab1Panel = new JPanel();
final JLabel t1ID = new JLabel("Tab 1");
JButton t1Test = new JButton("Test");
public static void main(String[] args)
{JFrame MainDisplay = new SwingTest();
MainDisplay.setVisible(true);
MainDisplay.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public SwingTest()
{super("SwingTest");
setSize(300, 300);
getContentPane().setLayout(null);
setLocationRelativeTo(null);
MainScreen.setBounds(0, 0, 300, 300);
MainScreen.add("Tab 0",tab0Layout());
MainScreen.add("Tab 1",tab1Layout());
getContentPane().add(MainScreen);
}
public JPanel tab0Layout()
{tab0Panel.setSize(300, 300);
t0ID.setBounds(100,100,60,20);
tab0Panel.add(t0ID);
t0Test.setBounds(100,150,60,20);
tab0Panel.add(t0Test);
t0Test.addActionListener
(new ActionListener()
{public void actionPerformed(ActionEvent e)
{iter++;
System.out.println("Iteration #"+iter+" Tab 0 listener alerted");
MainScreen.setComponentAt(0, tab0Layout());
revalidate();
repaint();
}
}
);
return tab0Panel;
}
public JPanel tab1Layout()
{tab1Panel.setSize(300, 300);
t1ID.setBounds(100,100,60,20);
tab1Panel.add(t1ID);
t1Test.setBounds(100,150,60,20);
tab1Panel.add(t1Test);
t1Test.addActionListener
(new ActionListener()
{public void actionPerformed(ActionEvent e)
{iter++;
System.out.println("Iteration #"+iter+" Tab 1 listener alerted");
MainScreen.setComponentAt(1, tab1Layout());
revalidate();
repaint();
}
}
);
return tab1Panel;
}
}
Thanks in advance for your help!
Obviously I'm doing something wrong and don't understand the cause.
Every time the first ActionListener runs, it calls
tab0Layout()adding a new ActionListener to the t0Test variable, and likewise, every time the second ActionListener runs, it callstab1Layout()adding a new ActionListener to the t1Test variable. This means, that each ActionListener adds a new copy of itself to its own button which each call, and this causes a bunch of listeners to be added to buttons, all calling at the same time. Not good.The solution is to add the listener once, and not within the listener.