如何在 JavaFX 应用程序中将文本设置为键盘按键上的标签?
How to set text to a label on keyboard key press in JavaFX application?
我正在使用 Scene Builder 制作 JavaFX 应用程序。我有 Main Class 用 main window 启动 Controller。
我在控制器中有一个标签class
我需要在主 window 中分配键盘按键。
示例:如果我在键盘上按“1”,标签文本应设置为“按下键 1。
如果我在键盘上按“2”,文本应设置为 "key 2 is pressed"
我该怎么做?
我尝试在初始化方法中使用此代码,但没有任何反应:
category1.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent ke) {
KeyCode kc = ke.getCode();
if((kc.equals(KeyCode.D))) {
category1.setText("Key D is pressed");
}
}
});
主要Class:
包裹 src.card;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.input.*;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
try {
Parent root = FXMLLoader.load(getClass().getResource("resources/fxml/card.fxml"));
Scene scene = new Scene(root, 1600, 600);
primaryStage.setScene(scene);
scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.setMaximized(true);
primaryStage.setResizable(true);
primaryStage.getIcons().add(new Image("src/card/resources/logo-icon.png"));
primaryStage.show();
//adding resize and drag primary stage
ResizeHelper.addResizeListener(primaryStage);
//assign ALT+ENTER to maximize window
final KeyCombination kb = new KeyCodeCombination(KeyCode.ENTER, KeyCombination.CONTROL_DOWN);
scene.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
if (kb.match(event)) {
primaryStage.setMaximized(!primaryStage.isMaximized());
primaryStage.setResizable(true);
Controller cont = Context.getInstance().getController();
if (!primaryStage.isMaximized()) {
cont.getBtnFont().setPrefWidth(20);
cont.getBtnPalette().setPrefWidth(20);
cont.getBtnQuestCards().setPrefWidth(20);
cont.getBtnNonQuestCards().setPrefWidth(20);
} else if (primaryStage.isMaximized()){
cont.getBtnFont().setPrefWidth(50);
cont.getBtnPalette().setPrefWidth(50);
cont.getBtnQuestCards().setPrefWidth(50);
cont.getBtnNonQuestCards().setPrefWidth(50
);
}
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
控制器:
@FXML private Label category1
@FXML public void initialize(URL location, ResourceBundle resources) {
category1.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent ke) {
KeyCode kc = ke.getCode();
if((kc.equals(KeyCode.D))) {
category1.setText("Key D is pressed");
}
}
});
//register Controller in Context Class
Context.getInstance().setController(this);
}
编辑:
我试过在初始化方法中使用它:
category1.getScene().setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent ke) {
KeyCode kc = ke.getCode();
if((kc.equals(KeyCode.D))) {
category1.setText("Key D is pressed");
}
}
});
我遇到了错误:
javafx.fxml.LoadException:
/D:/IDEA%20Projects/CategoryCards/out/production/CategoryCards/src/card/resources/fxml/card.fxml
at javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2625)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2603)
如果我从类别 1 中删除 getScene()
- 一切正常并启动应用程序
当我使用 getScene()
时,它似乎试图从外部文件夹而不是我的主文件夹中获取 fxml 文件,但我该如何解决这个问题?
您可以通过将按键事件 (setOnKeyPressed
) 设置为 Label
的父级来实现
而不是 Scene
。尝试向 Scene
添加事件会出错,因为 initialize
将在创建 Scene
.
之前调用
假设您有一个名为 sample.fxml
的 FXML 文件,在该文件中您有 GridPane
的 ID root
和一个 Label
的 ID category1
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.GridPane?>
<GridPane fx:controller="Controller"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10" fx:id="root">
<Label text="Category" fx:id="category1"/>
</GridPane>
并且您有名为 Controller
的控制器 class。要在按下任何键时更改 category1
的标签,首先您必须通过调用 category1
上的 setFocusTraversable
方法并传递 true
来设置 category1
焦点可遍历。然后你必须在 root
(parent of category1
) 上添加按键事件,如下所示
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable{
@FXML private Label category1;
@FXML private GridPane root;
@Override
public void initialize(URL location, ResourceBundle resources){
category1.setFocusTraversable(true);
root.setOnKeyPressed(this::handle);
}
private void handle(KeyEvent keyEvent){
category1.setText("Key " + keyEvent.getCode().getName() + " is pressed");
}
}
这里是 Main
class
的简单版本
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application{
public static void main(String[] args){
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
Scene scene = new Scene(root, 300, 275);
primaryStage.setScene(scene);
primaryStage.show();
}
}
我正在使用 Scene Builder 制作 JavaFX 应用程序。我有 Main Class 用 main window 启动 Controller。
我在控制器中有一个标签class
我需要在主 window 中分配键盘按键。
示例:如果我在键盘上按“1”,标签文本应设置为“按下键 1。
如果我在键盘上按“2”,文本应设置为 "key 2 is pressed"
我该怎么做?
我尝试在初始化方法中使用此代码,但没有任何反应:
category1.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent ke) {
KeyCode kc = ke.getCode();
if((kc.equals(KeyCode.D))) {
category1.setText("Key D is pressed");
}
}
});
主要Class: 包裹 src.card;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.input.*;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
try {
Parent root = FXMLLoader.load(getClass().getResource("resources/fxml/card.fxml"));
Scene scene = new Scene(root, 1600, 600);
primaryStage.setScene(scene);
scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.setMaximized(true);
primaryStage.setResizable(true);
primaryStage.getIcons().add(new Image("src/card/resources/logo-icon.png"));
primaryStage.show();
//adding resize and drag primary stage
ResizeHelper.addResizeListener(primaryStage);
//assign ALT+ENTER to maximize window
final KeyCombination kb = new KeyCodeCombination(KeyCode.ENTER, KeyCombination.CONTROL_DOWN);
scene.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
if (kb.match(event)) {
primaryStage.setMaximized(!primaryStage.isMaximized());
primaryStage.setResizable(true);
Controller cont = Context.getInstance().getController();
if (!primaryStage.isMaximized()) {
cont.getBtnFont().setPrefWidth(20);
cont.getBtnPalette().setPrefWidth(20);
cont.getBtnQuestCards().setPrefWidth(20);
cont.getBtnNonQuestCards().setPrefWidth(20);
} else if (primaryStage.isMaximized()){
cont.getBtnFont().setPrefWidth(50);
cont.getBtnPalette().setPrefWidth(50);
cont.getBtnQuestCards().setPrefWidth(50);
cont.getBtnNonQuestCards().setPrefWidth(50
);
}
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
控制器:
@FXML private Label category1
@FXML public void initialize(URL location, ResourceBundle resources) {
category1.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent ke) {
KeyCode kc = ke.getCode();
if((kc.equals(KeyCode.D))) {
category1.setText("Key D is pressed");
}
}
});
//register Controller in Context Class
Context.getInstance().setController(this);
}
编辑:
我试过在初始化方法中使用它:
category1.getScene().setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent ke) {
KeyCode kc = ke.getCode();
if((kc.equals(KeyCode.D))) {
category1.setText("Key D is pressed");
}
}
});
我遇到了错误:
javafx.fxml.LoadException:
/D:/IDEA%20Projects/CategoryCards/out/production/CategoryCards/src/card/resources/fxml/card.fxml
at javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2625)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2603)
如果我从类别 1 中删除 getScene()
- 一切正常并启动应用程序
当我使用 getScene()
时,它似乎试图从外部文件夹而不是我的主文件夹中获取 fxml 文件,但我该如何解决这个问题?
您可以通过将按键事件 (setOnKeyPressed
) 设置为 Label
的父级来实现
而不是 Scene
。尝试向 Scene
添加事件会出错,因为 initialize
将在创建 Scene
.
假设您有一个名为 sample.fxml
的 FXML 文件,在该文件中您有 GridPane
的 ID root
和一个 Label
的 ID category1
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.GridPane?>
<GridPane fx:controller="Controller"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10" fx:id="root">
<Label text="Category" fx:id="category1"/>
</GridPane>
并且您有名为 Controller
的控制器 class。要在按下任何键时更改 category1
的标签,首先您必须通过调用 category1
上的 setFocusTraversable
方法并传递 true
来设置 category1
焦点可遍历。然后你必须在 root
(parent of category1
) 上添加按键事件,如下所示
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable{
@FXML private Label category1;
@FXML private GridPane root;
@Override
public void initialize(URL location, ResourceBundle resources){
category1.setFocusTraversable(true);
root.setOnKeyPressed(this::handle);
}
private void handle(KeyEvent keyEvent){
category1.setText("Key " + keyEvent.getCode().getName() + " is pressed");
}
}
这里是 Main
class
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application{
public static void main(String[] args){
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
Scene scene = new Scene(root, 300, 275);
primaryStage.setScene(scene);
primaryStage.show();
}
}