1. 引言

1.1. 概述

在这个简短教程中,我们将探讨JavaFX的Button组件,并了解如何处理用户交互

1.2. JavaFX API

在Java 8、9和10中,开始使用JavaFX库无需额外设置。从JDK 11开始,项目将从JDK中移除,需要在pom.xml中添加以下依赖:

<dependencies>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-controls</artifactId>
        <version>${javafx.version}</version>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-fxml</artifactId>
        <version>${javafx.version}</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-maven-plugin</artifactId>
            <version>${javafx-maven-plugin.version}</version>
            <configuration>
                <mainClass>Main</mainClass>
            </configuration>
        </plugin>
    </plugins>
</build>

2. 应用程序设置

首先,让我们创建一个小型应用程序,以便专注于事件处理器。我们从创建一个简单的FXML布局开始,其中包含一个按钮:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane xmlns:fx="http://javafx.com/fxml"
    xmlns="http://javafx.com/javafx"
    fx:controller="com.baeldung.button.eventhandler.ButtonEventHandlerController"
    prefHeight="200.0" prefWidth="300.0">
    <center>
        <Button fx:id="button" HBox.hgrow="ALWAYS"/>
    </center>

    <bottom>
        <Label fx:id="label" text="Test label"/>
    </bottom>
</BorderPane>

接下来,创建ButtonEventHandlerController类。这个类负责连接UI元素和应用程序逻辑。我们在initialize方法中设置按钮的标签:

public class ButtonEventHandlerController {

    private static final Logger logger = LoggerFactory.getLogger(ButtonEventHandlerController.class);

    @FXML
    private Button button;

    @FXML
    private Label label;

    @FXML
    private void initialize() {
        button.setText("Click me");
    }
}

启动应用程序。我们应该在窗口底部看到一个名为“Click me”的按钮,以及一个测试标签:

应用程序预览

3. 点击事件

我们从处理简单的点击事件开始,在initialize方法中添加事件处理器:

button.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent event) {
        logger.info("OnAction {}", event);
    }
});

现在试一试。当我们点击按钮时,会看到新的日志消息:

INFO c.b.b.e.ButtonEventHandlerController - OnAction javafx.event.ActionEvent[source=Button[id=searchButton, styleClass=button]'Click me']

由于事件处理器接口只有一个方法,我们可以将其视为函数式接口,通过单个lambda表达式替换这些行,使代码更易读

searchButton.setOnAction(event -> logger.info("OnAction {}", event));

尝试添加另一个点击事件处理器。只需复制这一行并更改日志消息,以便我们在测试应用时能看到区别:

button.setOnAction(event -> logger.info("OnAction {}", event));
button.setOnAction(event -> logger.info("OnAction2 {}", event));

现在,当点击按钮时,我们只会看到“OnAction 2”消息。这是因为第二次setOnAction方法调用用第二个事件处理器替换了一个。

4. 不同类型的事件

我们还可以处理其他类型的事件,如鼠标按下/释放、拖动和键盘事件

让我们为按钮添加悬停效果。当鼠标光标开始悬停在按钮上时显示阴影,鼠标离开时移除效果:

Effect shadow = new DropShadow();
searchButton.setOnMouseEntered(e -> searchButton.setEffect(shadow));
searchButton.setOnMouseExited(e -> searchButton.setEffect(null));

5. 重用事件处理器

在某些情况下,我们可能希望多次使用同一个事件处理器。让我们创建一个事件处理器,当我们在按钮上使用次要鼠标按钮点击时,增加按钮的字体大小:

EventHandler<MouseEvent> rightClickHandler = event -> {
    if (MouseButton.SECONDARY.equals(event.getButton())) {
        button.setFont(new Font(button.getFont().getSize() + 1));
    }
};

但目前它没有功能,因为我们还没有将其与任何事件关联起来。让我们把这个事件处理器用于按钮的鼠标按下事件和标签:

button.setOnMousePressed(rightClickHandler);
label.setOnMousePressed(rightClickHandler);

现在,当我们测试应用并使用次要鼠标按钮点击标签或按钮时,会看到字体大小增加。

6. 总结

我们学习了如何为JavaFX按钮添加事件处理器,并根据事件类型执行不同的操作。

如往常一样,完整的代码实现可以在GitHub上找到。