【问题标题】:Java / JavaFX getting around final or effectively final, is this a good approach?Java / JavaFX 绕过最终或有效最终,这是一个好方法吗?
【发布时间】:2014-12-10 20:57:13
【问题描述】:

这感觉就像我在作弊或做错事。我是一名 Java 学生,从事一个简单的 JavaFX 项目。

当我在 flowPane 中循环并创建按钮时,我在内部类中使用循环计数器 i 时遇到了问题。这是我分配事件处理程序的部分。我以前处理过这个问题,我明白“最终”和“有效最终”之间的区别,所以我不相信我在问这个问题。

只是使用“int thisI = i”创建这个 i 的副本在设计上感觉是错误的。没有更好的方法来做到这一点吗?我研究了 lambda,它们也有“最终或有效最终”的要求。

这是我的代码,欢迎任何级别或批评或改进建议,谢谢!

private FlowPane addFlowPaneCenter() {

    FlowPane flow = new FlowPane();
    flow.setPadding(new Insets(0, 0, 0, 0));
    flow.setVgap(0);
    flow.setHgap(0);
    flow.setPrefWrapLength(WIDTH_OF_CENTER); // width of function buttons

    Button centerButtons[] = new Button[NUM_BUTTONS];
    ImageView centerImages[] = new ImageView[NUM_BUTTONS];
    for (int i=0; i < NUM_BUTTONS; i++) {
        centerImages[i] = new ImageView(
                new Image(Calculator.class.getResourceAsStream(
                "images/button-"+(i)+".png")));
        centerButtons[i] = new Button();
        centerButtons[i].setGraphic(centerImages[i]);
        centerButtons[i].setPadding(Insets.EMPTY);
        centerButtons[i].setId("button-"+(i));
        flow.getChildren().add(centerButtons[i]);

        // add a drop shadow on mouseenter
        DropShadow shadow = new DropShadow();

        // ***** here's the workaround is this really a good approach
        // to use this in the inner class instead of i? thanks *****
        int thisI = i;

        // set event handlers for click, mousein, mouseout
        centerButtons[i].setOnAction(new EventHandler<ActionEvent>() {
                @Override public void handle(ActionEvent e) {
                    // change graphic of button to down graphic
                    ImageView downImage = new ImageView(new 
                    Image(Calculator.class.getResourceAsStream(
                    "images/button-"+(thisI)+"D.png")));

                    // call function to effect button press
                    System.out.println("Button click");

                    // change graphic back
                    centerButtons[thisI].setGraphic(centerImages[thisI]);

                }});

        centerButtons[i].addEventHandler(MouseEvent.MOUSE_ENTERED, 
                new EventHandler<MouseEvent>() {
                        @Override public void handle(MouseEvent e) {
                        centerButtons[thisI].setEffect(shadow);
                        }
                    });

        centerButtons[i].addEventHandler(MouseEvent.MOUSE_EXITED, 
                new EventHandler<MouseEvent>() {
                        @Override public void handle(MouseEvent e) {
                        centerButtons[thisI].setEffect(null);
                        }
                    }); 
    }
    return flow;
}

【问题讨论】:

  • 哦,我想我应该移动“flow.getChildren().add(centerButtons[i]);”下课后

标签: java javafx event-handling final


【解决方案1】:

您可以完全删除数组 centerButtons 和 centerImages。而是为循环中的图像和按钮创建局部变量并使用它们,例如

final ImageView image = new ImageView(...);
final Button button = new Button();
button.setGraphic(centerImages[i]);
...

您可以在事件处理程序中使用局部变量,例如

button.setOnAction(new EventHandler<ActionEvent>() {
            @Override public void handle(ActionEvent e) {
                ...
                // change graphic back
                button.setGraphic(image);

            }});

我注意到两个小改进:

  • 尽量避免多次创建Image,因为每次创建Image都会重新加载实际数据。您的处理程序将为每次单击创建一个新图像。我通常在静态最终字段中创建图像。
  • 事件处理程序是练习 lambda 表达式的好机会。 :)

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2012-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-24
  • 2023-03-11
相关资源
最近更新 更多