我有一个比这复杂得多的应用程序,但这个简化的代码也有同样的问题。完整的应用程序在选项卡式窗格中有 4 个选项卡,并查询数据库以更新滚动窗格中的表。当请求每次搜索信息时,侦听器会针对每个请求触发多次,从而导致应用程序速度减慢至无法使用的程度。
以下最小化代码演示了该问题。每个选项卡上都有一个按钮,其中附加了一个侦听器。按钮被交替“按下”...选项卡 0、选项卡 1、选项卡 0、选项卡 1 等。系统输出显示乘法如何传播。迭代 #1 和 2 都很好...监听器每次都会被触发一次。迭代 3 到 6 显示每个监听器发射两次,尽管按钮每次按下一次。然后,迭代 7 到 14 显示每个侦听器触发 4 次。很明显,每次加倍都会通过多次查询数据库来获取相同的信息,从而大大减慢应用程序的速度。
系统输出: 迭代 #1 Tab 0 侦听器收到警报 迭代 #2 Tab 1 侦听器收到警报 迭代 #3 Tab 0 侦听器收到警报 迭代 #4 Tab 0 侦听器收到警报 迭代 #5 Tab 1 侦听器收到警报 迭代 #6 Tab 1 侦听器收到警报 迭代 #7 Tab 0 侦听器收到警报 迭代 #8 Tab 0 侦听器收到警报 迭代 #9 Tab 0 侦听器收到警报 迭代 #10 Tab 0 侦听器收到警报 迭代 #11 Tab 1 侦听器收到警报 迭代 #12 Tab 1 侦听器收到警报 迭代 #13 Tab 1 侦听器收到警报 迭代 #14 Tab 1 侦听器收到警报
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;
}
}
预先感谢您的帮助!
显然我做错了什么并且不明白原因。
每次第一个 ActionListener 运行时,它都会调用
tab0Layout()
将一个 new ActionListener 添加到 t0Test 变量,同样,每次第二个 ActionListener 运行时,它都会调用 tab1Layout()
将一个 new ActionListener 添加到 t1Test 变量。这意味着,每个 ActionListener 都会将自身的新副本添加到每个调用的自己的按钮中,这会导致将一堆侦听器添加到按钮中,所有侦听器同时调用。不好。
解决方案是添加一次监听器,而不是在监听器内添加。