简体   繁体   English

java:是否可以为按钮数组设置 lambda 表达式是一个 for 循环? 如果是这样怎么办?

[英]java: Is it possible to set a lambda expression for an array of Buttons is a for loop? If so how?

I want to be able to do something like this:我希望能够做这样的事情:

for(i = 0; i < 10; i++) {
    //if any button in the array is pressed, disable it.
    button[i].setOnAction( ae -> { button[i].setDisable(true) } );
}

However, I get a error saying "local variables referenced from a lambda expression must be final or effectively final" .但是,我收到一条错误消息,指出"local variables referenced from a lambda expression must be final or effectively final" How might I still do something like the code above (if it is even possible)?我怎么还能像上面的代码那样做(如果可能的话)? If it can't be done, what should be done instead to get a similar result?如果做不到,应该怎么做才能得到类似的结果?

As the error message says, local variables referenced from a lambda expression must be final or effectively final ("effectively final" meaning the compiler can make it final for you).正如错误消息所说,从 lambda 表达式引用的局部变量必须是最终的或有效最终的(“有效最终”意味着编译器可以为您使其成为最终的)。

Simple workaround:简单的解决方法:

for(i = 0; i < 10; i++) {
    final int ii = i;
    button[i].setOnAction( ae -> { button[ii].setDisable(true) } );
}

Since you are using lambdas, you can benefit also from other features of Java 8, like streams.由于您使用的是 lambda,您还可以从 Java 8 的其他功能(如流)中受益。

For instance, IntStream :例如, IntStream

A sequence of primitive int-valued elements supporting sequential and parallel aggregate operations.支持顺序和并行聚合操作的原始整数值元素序列。 This is the int primitive specialization of Stream.这是 Stream 的 int 原始特化。

can be used to replace the for loop:可用于替换 for 循环:

IntStream.range(0,10).forEach(i->{...});

so now you have an index that can be used to your purpose:所以现在你有一个可以用于你的目的的索引:

IntStream.range(0,10)
         .forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));

Also you can generate a stream from an array:您也可以从数组生成流:

 Stream.of(button).forEach(btn->{...});

In this case you won't have an index, so as @shmosel suggests, you can use the source of the event:在这种情况下,您将没有索引,因此正如@shmosel 所建议的,您可以使用事件的来源:

Stream.of(button)
          .forEach(btn->btn.setOnAction(ea->((Button)ea.getSource()).setDisable(true)));    

EDIT编辑

As @James_D suggests, there's no need of downcasting here:正如@James_D 所暗示的,这里没有必要贬低:

Stream.of(button)
      .forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));

In both cases, you can also benefit from parallel operations:在这两种情况下,您还可以从并行操作中受益:

IntStream.range(0,10).parallel()
         .forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));

Stream.of(button).parallel()
          .forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));

Use the Event to get the source Node .使用Event来获取源Node

for(int i = 0; i < button.length; i++)
{
     button[i].setOnAction(event ->{
         ((Button)event.getSource()).setDisable(true);
     });
}

Lambda expressions are effectively like an annonymous method which works on stream. Lambda 表达式实际上就像一个在流上工作的匿名方法。 In order to avoid any unsafe operations, Java has made that no external variables which can be modified, can be accessed in a lambda expression.为了避免任何不安全的操作,Java 规定在 lambda 表达式中不能访问可以修改的外部变量。

In order to work around it,为了解决这个问题,

final int index=button[i];最终 int index=button[i]; And use index instead of i inside your lambda expression.并在 lambda 表达式中使用 index 而不是i

You say If the button is pressed, but in your example all the buttons in the list will be disabled.您说如果按下按钮,但在您的示例中,列表中的所有按钮都将被禁用。 Try to associate a listener to each button rather than just disable it.尝试将侦听器与每个按钮相关联,而不仅仅是禁用它。

For the logic, do you mean something like that :对于逻辑,你的意思是这样的:

Arrays.asList(buttons).forEach(
        button -> button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                button.setEnabled(false);

            }
}));

I Also like Sedrick's answer but you have to add an action listener inside the loop .我也喜欢 Sedrick 的回答,但您必须在循环中添加一个动作侦听器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM