我是JavaFX的新手,使用setOnMouseClicked方法时遇到麻烦。在下面的代码中,我尝试在嵌套循环内添加事件处理程序以分配每个矩形,从而创建了一个事件处理程序,该事件处理程序在单击鼠标时将矩形变为灰色。它似乎根本不起作用,我不知道为什么。我是否缺少需要添加的内容?
public class Cinema extends Application {
@Override
public void start(Stage primaryStage) {
try {
Screen screen1 = new Screen(8, 14);
Pane root = FXMLLoader.load(getClass().getResource("Cinema.fxml"));
Scene scene = new Scene(root, 400, 400);
VBox seatHolder = new VBox(5);
seatHolder.setPrefWidth(root.getWidth());
seatHolder.setPrefHeight(root.getHeight());
seatHolder.prefWidthProperty().bind(root.widthProperty());
seatHolder.prefHeightProperty().bind(root.heightProperty());
seatHolder.setAlignment(Pos.CENTER);
for (int i = 0; i < screen1.getSeats().length; i++) {
HBox hbox = new HBox();
hbox.setSpacing(1);
hbox.setAlignment(Pos.CENTER);
for (int j = 0; j < screen1.getSeats()[i].length; j++) {
Rectangle r = new Rectangle(30, 40);
r.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
r.setFill(Color.GREEN);
}
});
hbox.getChildren().add(r);
r.widthProperty().bind(root.heightProperty().divide(15));
r.heightProperty().bind(root.widthProperty().divide(30));
if (screen1.getSeats()[i][j] != null) {
r.setFill(Color.RED);
}
else {
r.setFill(Color.BLUE);
}
}
seatHolder.getChildren().add(hbox);
}
root.getChildren().add(seatHolder);
HBox screenHolder = new HBox();
screenHolder.setPrefWidth(root.getWidth());
screenHolder.setPrefHeight(root.getHeight());
screenHolder.prefWidthProperty().bind(root.widthProperty());
screenHolder.prefHeightProperty().bind(root.heightProperty());
Rectangle screen = new Rectangle(350, 25);
screen.widthProperty().bind(seatHolder.widthProperty());
screen.setFill(Color.LIGHTSLATEGREY);
screenHolder.getChildren().add(screen);
screenHolder.setAlignment(Pos.BOTTOM_CENTER);
root.getChildren().add(screenHolder);
primaryStage.setScene(scene);
primaryStage.show();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
编辑: 这是FXML的内容,根节点只是一个空白窗格
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.shape.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.Pane?>
<Pane maxHeight="-Infinity" maxWidth="-Infinity"
minHeight="-Infinity" minWidth="-Infinity" prefHeight="558.0"
prefWidth="714.0" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1" />
自定义屏幕类还定义了循环中使用的2d席位数组
public class Screen {
private String [][] seats;
public Screen(int rows, int columns) {
this.seats = new String [rows][columns];
}
public String[][] getSeats() {
return seats;
}
}
答案 0 :(得分:2)
问题在于,seatHolder
窗格之前已添加screenHolder
窗格。这导致screenHolder
在seatHolder
上方。您可以通过添加screenHolder.setStyle("-fx-background-color: #ffff00;");
轻松地看到这一点。在这种情况下,永远不会调用您的EventHandler。您可以通过在处理程序方法中打印一些内容来进行检查。
您可以通过更改将窗格添加到根窗格(root.getChildren().addAll(screenHolder, seatHolder);
)的顺序来解决此问题。第一个是最低的,最后一个是最高的。另外,您也可以更改布局。
我建议更改布局并使用BorderPane:
BorderPane root = new BorderPane();
Scene scene = new Scene(root, 400, 400);
VBox seatHolder = new VBox(5);
seatHolder.setAlignment(Pos.CENTER);
// setup seatHolder as before but use
root.setCenter(seatHolder);
HBox screenHolder = new HBox();
Rectangle screen = new Rectangle(350, 25);
screen.widthProperty().bind(seatHolder.widthProperty());
screen.setFill(Color.LIGHTSLATEGREY);
screenHolder.getChildren().add(screen);
screenHolder.setAlignment(Pos.BOTTOM_CENTER);
root.setBottom(screenHolder);
primaryStage.setScene(scene);
primaryStage.show();
这应该为您工作。在这种情况下,您甚至不需要fxml文件。
答案 1 :(得分:1)
我认为绑定r
的值与在处理函数中使用它的时间可能是一个问题。
在您的EventHandler中,尝试以下操作
@Override
public void handle(MouseEvent event) {
Rectangle clicked = (Rectangle) event.getSource();
clicked.setFill(Color.GREEN);
}
而不是在处理程序中引用r
。
编辑:
看起来screenHolder
涵盖了所有席位,因此您的点击从未注册。尝试设置screenHolder
尺寸以匹配屏幕本身:
Rectangle screen = new Rectangle(350, 25);
screenHolder.setPrefWidth(screen.getWidth());
screenHolder.setPrefHeight(screen.getHeight());
screenHolder.prefWidthProperty().bind(screen.heightProperty());
screenHolder.prefHeightProperty().bind(screen.heightProperty());