尝试理解为什么动作监听器会多次触发

问题描述 投票:0回答:1

我有一个比这复杂得多的应用程序,但这个简化的代码也有同样的问题。完整的应用程序在选项卡式窗格中有 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;
        }
    }
 

预先感谢您的帮助!

显然我做错了什么并且不明白原因。

java swing actionlistener
1个回答
0
投票

每次第一个 ActionListener 运行时,它都会调用

tab0Layout()
将一个 new ActionListener 添加到 t0Test 变量,同样,每次第二个 ActionListener 运行时,它都会调用
tab1Layout()
将一个 new ActionListener 添加到 t1Test 变量。这意味着,每个 ActionListener 都会将自身的新副本添加到每个调用的自己的按钮中,这会导致将一堆侦听器添加到按钮中,所有侦听器同时调用。不好。

解决方案是添加一次监听器,而不是在监听器内添加。

© www.soinside.com 2019 - 2024. All rights reserved.