在Java中向ActionListener传递变量

7

我有一个类似下面的代码:

    for(int i=0;i<10;i++){
        button=new JButton(buttons[i]);
        button.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                setPage(i);
            }
        });
        menu.add(button);
    }

然而,在ActionListener类的范围内未定义变量i。我该如何传递这个变量?

2
当监听器被触发时,i肯定会一直是10。 (final的要求不是很好吗?;) - Tom Hawtin - tackline
3个回答

22

一种完全不同的方法是向按钮添加属性,并在您的动作监听器中检索该属性。例如:

button=new JButton(buttons[i]);
button.putClientProperty( "page", i );
button.addActionListener(new ActionListener(){
   public void actionPerformed(ActionEvent e) {
      setPage((Integer)((JButton)e.getSource()).getClientProperty( "page" ));
   }
});

这应该是被接受的答案。这是一个更简单的方法。坦白说,我不知道按钮可以像那样添加属性。非常好的答案。 - Akshay Damle
也许提问者决定不再使用匿名类,因此他接受了JB Nizet的答案。 - Xel
如果您正在使用一个没有“putClientProperty()”方法的类,例如javax的Timer,该怎么办? - Markus Tonsaker

21

除了Hovercraft的回答之外,你还应该注意到并不一定强制使用匿名类作为事件监听器。Hovercraft回答的代码类似于以下代码:

private class PageActionListener implements ActionListener {
    private int page;

    public PageActionListener(int page) {
        this.page = page;
    }

    public void actionPerformed(ActionEvent e) {
        setPage(page);
    }
}

...

for(int i = 0; i < 10; i++){
    button = new JButton(buttons[i]);
    button.addActionListener(new PageActionListener(i));
    menu.add(button);
}

我喜欢这种方法,比在循环中创建一个最终变量更好(当然这是个人偏好)。加一分以纠正负评。 - Robin

13

变量i实际上在ActionListener的范围内,但由于您正在尝试在内部类中使用局部变量,因此该变量必须是final。因此,您可以使用final变量:

for(int i=0;i<10;i++){
    final int index = i;
    button=new JButton(buttons[i]);
    button.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
            setPage(index);
        }
    });
    menu.add(button);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接