当前位置: 首页 > 知识库问答 >
问题:

包含EventHandler的循环没有按照javafx的预期工作?

鞠泰平
2023-03-14

我是JavaFX新手,在使用setOnMouse点击方法时遇到了问题。在下面的代码中,我尝试在嵌套循环中添加一个事件处理程序,为创建的每个矩形分配一个事件处理程序,单击鼠标后,该事件处理程序将矩形变为灰色。它似乎根本不起作用,我不知道为什么。我是否遗漏了需要添加的内容?

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;
    }
}

共有2个答案

谢和颂
2023-03-14

我认为这可能是绑定r值与在处理程序函数中使用它时的问题。

在EventHandler中,尝试以下操作

@Override
public void handle(MouseEvent event) {
  Rectangle clicked = (Rectangle) event.getSource();
  clicked.setFill(Color.GREEN);
}

而不是在处理程序中引用r

编辑:看起来屏幕支架覆盖了所有的座位,所以你的点击永远不会注册。尝试设置屏幕支架尺寸以匹配屏幕本身:

Rectangle screen = new Rectangle(350, 25);

screenHolder.setPrefWidth(screen.getWidth());
screenHolder.setPrefHeight(screen.getHeight());
screenHolder.prefWidthProperty().bind(screen.heightProperty());
screenHolder.prefHeightProperty().bind(screen.heightProperty());
岳炎彬
2023-03-14

问题是在屏幕支架窗格之前添加了seatHolder窗格。这会导致屏幕支架位于座椅支架上方。您可以通过添加屏幕支架轻松看到这一点。setStyle(“-fx背景色:#ffff00;”) 。在这种情况下,永远不会调用EventHandler。您可以通过在handler方法中打印一些内容来检查这一点。

可以通过更改窗格添加到根窗格的顺序(root.getChildren())来解决此问题。addAll(屏幕支架、seatHolder) )。第一个是最低的,最后一个是最高的。或者,您也可以更改布局。

我建议更改布局并使用边框窗格:

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文件。

 类似资料:
  • 我有一个用例,我需要使用Kafka进行批处理。假设在1分钟内有大约100个请求,我不想立即发布每个请求,而是想将所有100个请求分批发布到topic一次。 但是使用以下配置,批处理不会发生,一旦发送消息,它就会发布到主题并同时在消费者中接收 生产者配置 消费者配置 在这里,我设置了 linger.ms = 60000,根据我的理解,如果 linger.ms 设置为某个值,那么即使发送方线程更早变得

  • 我正试图将一个阻塞消费者集成为Reactor铝-SR1中的助焊剂订户。我想使用一个并行调度器,并发地执行阻塞操作。 我实现了一个主类来描述我意图:

  • 我在使用R的group_by和SUMMARY函数时遇到了一些问题,我想知道你们是否可以帮我一些忙。我有一张类似的表格: 我试图使用dplyr的group_by和SUMMARY来找到频率列的平均值。下面是我的示例代码: 我所期望的是,一个表格被吐出来,分解按单个类别分组的平均频率,如下所示: 但是,我收到的是一个按类别分组的表,每个类别接收整个表的平均值,如下所示: 有什么线索吗?我应该说我是初学者

  • 以下switch语句具有奇怪的行为: 我认为,当cat命令在被执行时失败时,“after cat”将被写入,而||之后的部分将被执行。但是,当我查看输出时,似乎在回显“后猫”后会发生中断,因此实际状态不会改变,将再次进入。然后stty也会失败(因为串行适配器丢失)。之后,cat命令againt在开始时失败,但现在进入“catch”块。。。。 下面是相关的输出: 我做错了什么?

  • 在我的应用程序中,我有一个带有VBox的ScrollPane,它可能包含0到1000个窗格,每个窗格的设置高度为90。每个窗格都有相关的项目,这些项目可以从内部的一个按钮加载,该按钮清除VBox并添加其子项,同时还有一个“返回结果”按钮,该按钮加载前一个列表并应该返回到滚动窗格中的相同位置。但是,setVvalue()似乎不起作用。窗格和它们的子级是同一类的。 setVvalue()起作用,并在打

  • 我已经配置了log4j2.xml文件,application.log文件将被创建,它应该每天翻转。 但是在JVM中,applicatoin.log文件在10MB之后会翻转,如果翻转三次,第一个文件会被覆盖。也就是说我随时都application.logapplication-2020-10-16.log.zip. 为什么log4j2(v2.13)即使配置为每日,也会每10MB滚动一次文件?任何在l