java 尝试理解为什么一个actionlistener会多次触发[关闭]

jjjwad0x  于 12个月前  发布在  Java
关注(0)|答案(1)|浏览(111)

已关闭此问题为not reproducible or was caused by typos。它目前不接受回答。

此问题是由打印错误或无法再重现的问题引起的。虽然类似的问题可能是on-topic在这里,这一个是解决的方式不太可能帮助未来的读者。
2天前关闭。
Improve this question
我有一个比这个复杂得多的应用程序,但这个简化的代码也有同样的问题。完整的应用程序在选项卡式窗格中有4个选项卡,并查询数据库以更新滚动窗格中的表。当每次请求搜索信息时,侦听器会对每个请求触发多次,导致应用程序变慢,直至无法使用。
下面最小化的代码演示了这个问题。每个选项卡上都有一个附加了侦听器的按钮。这些按钮交替地被“按下”......选项卡0,选项卡1,选项卡0,选项卡1,等等。系统输出显示乘法如何传播。迭代#1和#2都很好...侦听器每次被触发一次。迭代3到6示出了每个收听者发射两次,尽管按钮每次被按下一次。迭代7到14然后示出每个收听者发射4次。很明显,每次都要加倍查询数据库以获得相同的信息,这会大大降低应用程序的速度。

系统输出:

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

代码如下:

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;
        }
    }

提前感谢您的帮助!
显然我做错了什么,不明白原因。

von4xj4u

von4xj4u1#

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

public class SwingTest extends JFrame  {
    //...
    
    JButton t0Test = new JButton("Test"); 
    
    //...

    public static void main(String[] args) {
        //...
    }

    public SwingTest() {
        //...
        
        MainScreen.add("Tab 0",tab0Layout());
        
        //...
    }

    public JPanel tab0Layout() {
        // ...
        t0Test.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // ...
                MainScreen.setComponentAt(0, tab0Layout()); // ***** HERE
                // ..
            }
        });    
        return tab0Panel;
    }

    // ...
}

解决方案是只添加一次侦听器,而不是在侦听器中添加。

相关问题