简体   繁体   English

在 java 中为不同的元素添加大量监听器的正确方法是什么?

[英]Which is the correct way to add a huge amount of listeners to different elements in java?

I have a controller class in a JavaFX program which is handling numerous Nodes.我在 JavaFX 程序中有一个 controller class 正在处理大量节点。 I created a method addEventListeners which looks like:我创建了一个addEventListeners方法,它看起来像:

    cleanButton.setOnAction(e -> {
        ...
    });

    advSett.setOnAction(e -> {
        ...
    });

    imageLoaderItem.setOnAction(e -> {
        ...
    });

    outputButton.setOnAction(e -> {
        ...
    });

And so on for each element handled by the controller. This method is occupying 300 lines of code making the controller class quite messy.对于 controller 处理的每个元素,依此类推。此方法占用 300 行代码,使 controller class 相当混乱。 I was wondering, is there a cleaner way of adding the listeners?我想知道,是否有更简洁的方式来添加听众?

This answer is complementary and additional to Vinz's answer .这个答案是对Vinz答案的补充和补充。 The information in this answer can be used in combination with the suggestions suggested in that answer or separately.此答案中的信息可以与该答案中建议的建议结合使用,也可以单独使用。

As noted in the Introduction to FXML documentation , you can directly associate events from FXML to Java or script code, using the # prefix on the event name in FXML.FXML 文档简介中所述,您可以直接将事件从 FXML 关联到 Java 或脚本代码,使用 FXML 中事件名称的#前缀。

Using the # injection method is a bit more succinct than invoking setOnAction .使用#方法比调用setOnAction更简洁。 It is a matter of stylistic or personal preference as to which method to use.使用哪种方法取决于风格或个人偏好。 Both approaches are valid and the results are identical.这两种方法都是有效的,结果是相同的。 Neither way is "correct" or "incorrect".两种方式都不是“正确”或“不正确”。

Paraphrasing from the documentation, given this definition:从文档中解释,给出这个定义:

<VBox fx:controller="com.foo.MyController"
    xmlns:fx="http://javafx.com/fxml">
    <children>
        <Button text="Click Me!" onAction="#handleButtonAction"/>
    </children>
</VBox> 

You can write:你可以写:

package com.foo;

import javafx.event.ActionEvent;

public class MyController {
    public void handleButtonAction(ActionEvent event) {
        System.out.println("You clicked me!");
    }
}

Or, if you prefer using @FXML and not public methods, you can write:或者,如果您更喜欢使用@FXML而不是公共方法,您可以编写:

package com.foo;

import javafx.fxml.FXML;
import javafx.event.ActionEvent;

public class MyController {
    @FXML
    private void handleButtonAction(ActionEvent event) {
        System.out.println("You clicked me!");
    }
}

Further, the event parameter is optional, so you can just leave it out if not needed, and write:此外,事件参数是可选的,因此如果不需要,您可以将其省略,并编写:

package com.foo;

public class MyController {
    public void handleButtonAction() {
        System.out.println("You clicked me!");
    }
}

Any of the above methods is equivalent to writing (after also adding an fx:id="button" attribute in the FXML):上述任何一种方法都等同于编写(在 FXML 中还添加了一个fx:id="button"属性之后):

package com.foo;

import javafx.fxml.FXML;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;

public class MyController implements Initializable {
    @FXML private Button button;

    @FXML
    protected void initialize()
        button.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                System.out.println("You clicked me!");
            }
        });
    }
}

If multiple actions should have the same handler, you can reference the same handler name and implementation multiple times in the FXML file, like below:如果多个操作应具有相同的处理程序,您可以在 FXML 文件中多次引用相同的处理程序名称和实现,如下所示:

<VBox fx:controller="com.foo.MyController"
    xmlns:fx="http://javafx.com/fxml">
    <children>
        <Button text="Click Me!" onAction="#handleButtonAction"/>
        <Button text="Click Me Too!" onAction="#handleButtonAction"/>
    </children>
</VBox> 

Complementary question:补充问题:

As correctly pointed out in the comments, splitting your Controller into several smaller ones is usually a good idea when you are facing such problems.正如评论中正确指出的那样,当您遇到此类问题时,将您的 Controller 分成几个较小的通常是个好主意。 Still, there are ways to avoid repetition of the same or similar instructions.尽管如此,还是有一些方法可以避免重复相同或相似的指令。 If all your Buttons / Nodes do the same, you can simply do this:如果你所有的按钮/节点都做同样的事情,你可以简单地这样做:

private void addEventListener(final ButtonBase element) {
    element.setOnAction(e -> {
        //do the thing
    });
}

If most of your Nodes do the same and only two or three differ, then you can expand the same method like so:如果你的大多数节点都做同样的事情,只有两三个不同,那么你可以像这样扩展相同的方法:

private void addEventListener(final ButtonBase element) {
        if (element == cleanButton) {
            element.setOnAction(e -> {
                //do the thing
            });
        } else {
            element.setOnAction(e -> {
                //do the other thing
            });
        }
}

If you have identifyable groups of buttons that do the same, say group A doing x and group B doing y, then you can for example add them to a set each and handle them this way如果你有可识别的按钮组做同样的事情,比如 A 组做 x,B 组做 y,那么你可以将它们分别添加到一个集合中并以这种方式处理它们

private void addEventListener(final ButtonBase element) {
        if (groupA.contains(element)) {
            element.setOnAction(e -> {
                //do the thing for A
            });
        } else {
            element.setOnAction(e -> {
                //do the other thing
            });
        }
    }

Finally, you can also flip this on its head.最后,您还可以将其翻转过来。 If the common denominator is the event, rather than the Nodes, then you can also refactor your function to handle the event on the specific element it came from如果共同点是事件,而不是节点,那么您还可以重构 function 以处理来自特定元素的事件

private void handleButtonClicks(final javafx.event.ActionEvent mouseEvent) {
        switch (mouseEvent.getSource()) {
            case cleanButton:
                // and so on
            default:
     }
}

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

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