Цикл, содержащий EventHandler, не работает, как предназначено для javafx? - PullRequest
2 голосов
/ 11 марта 2019

Я новичок в JavaFX и у меня возникли проблемы с использованием метода setOnMouseClicked. В приведенном ниже коде я попытался добавить обработчик событий во вложенный цикл, чтобы назначить каждому прямоугольнику созданный eventHandler, который при щелчке мыши делает прямоугольник серым. Кажется, это не работает, и я не могу понять, почему. Я что-то упускаю, что нужно добавить?

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

Edit: Это содержимое 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" />

Также пользовательский класс экрана определяет массив 2-х мест, используемый в цикле

public class Screen {

    private String [][] seats;

    public Screen(int rows, int columns) {

        this.seats = new String [rows][columns];
    }

    public String[][] getSeats() {

        return seats;
    }
}

Ответы [ 2 ]

2 голосов
/ 11 марта 2019

Проблема в том, что панель 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 голос
/ 11 марта 2019

Я думаю, что это может быть проблемой, когда значение 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());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...