java:是否可以将按钮数组的lambda表达式设置为for循环?如果是,怎么做?
我希望能够做到以下几点:java:是否可以将按钮数组的lambda表达式设置为for循环?如果是,怎么做?,java,javafx,Java,Javafx,我希望能够做到以下几点: for(i = 0; i < 10; i++) { //if any button in the array is pressed, disable it. button[i].setOnAction( ae -> { button[i].setDisable(true) } ); } (i=0;i{button[i].setDisable(true)}); } 但是,我得到一个错误,它说“从lambda表达式引用的局部变量必须是fina
for(i = 0; i < 10; i++) {
//if any button in the array is pressed, disable it.
button[i].setOnAction( ae -> { button[i].setDisable(true) } );
}
(i=0;i<10;i++)的{
//如果按下阵列中的任何按钮,请将其禁用。
按钮[i].setOnAction(ae->{button[i].setDisable(true)});
}
但是,我得到一个错误,它说“从lambda表达式引用的局部变量必须是final或实际上是final”。我怎样才能继续执行上面的代码(如果可能的话)?如果不能这样做,那么应该怎么做才能得到类似的结果呢?正如错误消息所说,从lambda表达式引用的局部变量必须是final或effective final(“effective final”意味着编译器可以为您设置为final) 简单的解决方法:
for(i = 0; i < 10; i++) {
final int ii = i;
button[i].setOnAction( ae -> { button[ii].setDisable(true) } );
}
(i=0;i<10;i++)的{
最终int ii=i;
按钮[i].setOnAction(ae->{button[ii].setDisable(true)});
}
因为您使用的是lambdas,所以您还可以从Java8的其他功能(如streams)中获益
例如,IntStream
:
支持顺序和并行聚合操作的原始int值元素序列。这是流的int原语专门化
可用于替换for循环:
IntStream.range(0,10).forEach(i->{...});
因此,现在您有了一个可用于您的目的的索引:
IntStream.range(0,10)
.forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));
您还可以从阵列生成流:
Stream.of(button).forEach(btn->{...});
在这种情况下,您将没有索引,因此@shmosel建议,您可以使用事件源:
Stream.of(button)
.forEach(btn->btn.setOnAction(ea->((Button)ea.getSource()).setDisable(true)));
编辑
正如@James_D所建议的,这里没有必要贬低:
Stream.of(button)
.forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));
在这两种情况下,您还可以从并行操作中获益:
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)));
使用
事件
获取源节点
for(int i = 0; i < button.length; i++)
{
button[i].setOnAction(event ->{
((Button)event.getSource()).setDisable(true);
});
}
for(int i=0;i{
((按钮)event.getSource()).setDisable(true);
});
}
Lambda表达式实际上类似于在流上工作的匿名方法。为了避免任何不安全的操作,Java已经做出了这样的规定:不能在lambda表达式中访问任何可以修改的外部变量
为了解决这个问题
最终整数索引=按钮[i];
在lambda表达式中使用index而不是i。您说如果按钮被按下,但在您的示例中,列表中的所有按钮都将被禁用。尝试将侦听器与每个按钮关联,而不仅仅是禁用它 就逻辑而言,你的意思是这样的吗:
Arrays.asList(buttons).forEach(
button -> button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
button.setEnabled(false);
}
}));
我也喜欢塞德里克的回答,但你必须在循环中添加一个动作监听器。这很有效,谢谢。我来自C++编程背景,java中的这类东西有时会让我失望…就像当比较字符串一样。感谢您快速准确的回答。您也可以参考
按钮[i]
,然后重复使用它<代码>按钮电流=按钮[i]和电流.setDisable(真)代码>在lambda中。如果您想知道原因:变量值是按值传递到lambda中的,我想他们希望在以后的版本中保留通过引用传递非最终变量的可能性。它还避免了混淆,即()->{i=5;}
实际上不会更改i
(如果在i
不是最终值的情况下允许该lambda)。您应该能够从ActionEvent
获取按钮,而不是另一个数组查找
example不需要在事件处理程序中获取操作事件的源。变量btn
在这里的作用域中(这样可以避免难看的向下转换)?我认为所有的行动都需要在外汇市场上进行thread@Adam节点:“节点对象可以在任何线程上构造和修改,只要它们尚未连接到场景。应用程序必须在JavaFX应用程序线程上将节点连接到场景,并修改已连接到场景的节点。”不过,只需10个按钮,@jewelsea如果我错了,请纠正我,但在本例中,我们只是将事件处理程序添加到节点集合中,这不会影响它们的呈现。即使使用附加到场景的节点,也可以执行此操作。这与单击时禁用节点的操作无关,该操作将在JavaFX应用程序线程上执行。当然,如果节点已经连接到场景,与渲染相关的操作将失败。Jose,这类操作的并行代码可能会很好地工作,但是,在大多数情况下,我不建议这样做。仍然存在轻微(尽管不太可能)的风险,即它可能会同时产生副作用(例如,onAction是一个属性,有人可以设置一个侦听器来访问场景图)。此外,并行化setter将比顺序代码执行得慢,除非您正在设置~10000个操作侦听器。对于另一个堆栈溢出问题或询问。