【问题标题】:How can I change the scene By pressing a specific key(b) on the the keyboard?如何通过按键盘上的特定键 (b) 来更改场景?
【发布时间】:2022-02-02 06:49:37
【问题描述】:

在我的应用程序中,有两个场景:mainScenebossScene,其中mainScene 用于启动应用程序。

  • 我正在尝试实现老板键功能,通过按键盘上的“b”键应将场景更改为bossScene。并且按下bossScene中的按钮应该切换回mainScene

    我在 InteliJ 上收到一条错误消息,提示“无法解析列表中的方法 setOnKeyPressed

我的代码:

    public void start(Stage stage) throws Exception {

    stage.setTitle("BossKey Example");

    // Scene and layout for the main view
    VBox root = new VBox();
    Scene mainScene = new Scene(root, 500, 300);

    // Scene for the BOSS view
    Scene bossScene = new Scene(new Label("Nothing suspicious here"), 500, 300);

    List<TextField> fields = new ArrayList<TextField>();
    for (int i = 0; i < 10; i++) {
        fields.add(new TextField());

    }

    fields.setOnKeyPressed(new EventHandler<KeyEvent>() {
        @Override
        public void handle(KeyEvent keyEvent) {
            switch (keyEvent.getCharacter()){
                case "b": stage.setScene(bossScene); break;
            }
        }
    });

/////// 添加了addEventFilter,还是不行

   mainScene.addEventFilter(KeyEvent.KEY_PRESSED, new 
             EventHandler<KeyEvent() {

        @Override
        public void handle(KeyEvent keyEvent) {
            switch (keyEvent.getCharacter()){
                case "b": stage.setScene(bossScene); break;
            }
            keyEvent.consume();

        }

            });


    // Create components for main view
    root.getChildren().addAll(fields);
    root.getChildren().add(new Button("Hello!"));

    stage.setScene(mainScene);
    stage.show();

}

}

【问题讨论】:

  • mainScene.setOnKeyPressed(…)
  • @James_D 我也试过了,但是它没有显示错误,按下它永远不会工作。
  • 尝试添加一个事件过滤器。文本字段可能正在使用该事件。
  • mainScene.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler&lt;KeyEvent&gt;() { @Override public void handle(KeyEvent keyEvent) { switch (keyEvent.getCharacter()){ case "b": stage.setScene(bossScene); break; } keyEvent.consume(); } }); 但还是没有得到输出
  • 阅读有关 java 基础知识的教程,以便您了解错误消息。然后修复它。如果遇到问题,请提供 minimal reproducible example 说明问题所在

标签: javafx


【解决方案1】:

组合键过滤器

您应该在事件过滤器中使用组合键,例如 CTRL+B 或 SHORTCUT+B。

有关如何应用组合键的详细信息,请参阅:

为什么组合键优于过滤字符“b”:

  • 如果您过滤“b”字符,如果大写锁定关闭,该功能将不起作用。
  • 如果您过滤“b”字符,您将无法在文本字段中输入“b”。

你可能认为你可以写scene.setOnKeyPressed(...),但是,在很多情况下这不会像预期的那样工作。需要过滤器而不是按键事件处理程序,因为如果您使用处理程序,键事件可能会被文本字段等焦点字段消耗,因此处理程序实现可能不会在所有需要的情况下激活。

对组合键进行过滤可避免尝试处理字符按键的问题。组合键依赖于表示按下的物理键的键代码,而不依赖于其他键的状态,例如大写锁定,除非您为此明确添加额外的逻辑。

如果您不了解事件过滤器和事件处理程序之间的区别以及事件分派的捕获和冒泡阶段,那么请学习:

KeyCombination 过滤器实现

final EventHandler<KeyEvent> bossEventFilter = new EventHandler<>() {
    final KeyCombination bossKeyCombo = new KeyCodeCombination(
            KeyCode.B,
            KeyCombination.CONTROL_DOWN
    );

    public void handle(KeyEvent e) {
        if (bossKeyCombo.match(e)) {
            if (stage.getScene() == mainScene) {
                stage.setScene(bossScene);
            } else if (stage.getScene() == bossScene) {
                stage.setScene(mainScene);
            }

            e.consume();
        }
    }
};

mainScene.addEventFilter(KeyEvent.KEY_PRESSED, bossEventFilter);
bossScene.addEventFilter(KeyEvent.KEY_PRESSED, bossEventFilter);

加速器替代

可以使用加速器代替事件过滤器。有关应用加速器的信息也在对链接问题的回答中,我不会在此处进一步详细说明此替代方案。

示例解决方案

独立可执行示例代码:

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.*;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import java.io.IOException;

public class SceneSwap extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        final Scene mainScene = new Scene(
                createLayout(
                        "Press CTRL+B to enter boss mode",
                        Color.PALEGREEN
                )
        );
        final Scene bossScene = new Scene(
                createLayout(
                        "Press CTRL+B to exit boss mode",
                        Color.PALEGOLDENROD
                )
        );

        final EventHandler<KeyEvent> bossEventFilter = new EventHandler<>() {
            final KeyCombination bossKeyCombo = new KeyCodeCombination(
                    KeyCode.B,
                    KeyCombination.CONTROL_DOWN
            );

            public void handle(KeyEvent e) {
                if (bossKeyCombo.match(e)) {
                    if (stage.getScene() == mainScene) {
                        stage.setScene(bossScene);
                    } else if (stage.getScene() == bossScene) {
                        stage.setScene(mainScene);
                    }

                    e.consume();
                }
            }
        };

        mainScene.addEventFilter(KeyEvent.KEY_PRESSED, bossEventFilter);
        bossScene.addEventFilter(KeyEvent.KEY_PRESSED, bossEventFilter);

        stage.setScene(mainScene);
        stage.show();
    }

    private VBox createLayout(String text, Color color) {
        VBox mainLayout = new VBox(10,
                new Label(text),
                new TextField()
        );
        mainLayout.setPadding(new Insets(10));
        mainLayout.setStyle("-fx-background: " + toCssColor(color));

        return mainLayout;
    }

    private String toCssColor(Color color) {
        int r = (int) Math.round(color.getRed() * 255.0);
        int g = (int) Math.round(color.getGreen() * 255.0);
        int b = (int) Math.round(color.getBlue() * 255.0);
        int o = (int) Math.round(color.getOpacity() * 255.0);

        return String.format("#%02x%02x%02x%02x" , r, g, b, o);
    }

    public static void main(String[] args) {
        launch();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 2013-03-25
    • 1970-01-01
    • 2017-06-11
    • 1970-01-01
    • 2016-12-03
    • 2012-10-21
    相关资源
    最近更新 更多