GridPane 充当 mouseTransparent 尽管未设置

GridPane acts as mouseTransparent although not set

我想做什么?

我遇到了基于 fxml 的 javafx 应用程序的问题。我想创建一个简单的表格 sheet 来输入一些数值,这些数值应该在确认后存储在文件中。

问题是什么?

除了我不能用鼠标单击两个 GridPanes 中的元素外,该表单完美地完成了它应该做的事情。我可以通过按选项卡按钮切换 TextFields 输入值,但这当然不是理想的方式。我已经直接在 AnchorPane 中添加了 TextFields 和 CheckBoxes,它们是可点击的,但在 GridPanes 中这不起作用。同一个 AnchorPane 中的 FlowPane 也可以正常工作。

对我来说,GridPanes 的行为就好像它被设置为 mouseTransparent="true",但事实并非如此,我已经尝试过将其显式设置为 false。我找不到这种行为的原因,所以也许你们中有人有想法。

编辑:在同一个选项卡中尝试添加 GridPane 后,我发现这不是此文件中的一般 GridPane 问题。对于只有复选框和只有一个锚点的 GridPane,可以访问该元素。是否有一些重叠阻止通过鼠标进行访问?

在单独的 class 的初始化函数中设置场景:

        BorderPane root = FXMLLoader.load(getClass().getResource("..\initializeSeason\InitializeSeason.fxml"));
        Scene scene = new Scene(root,600,900);
        stage.setScene(scene);
        stage.show();

xfml 文件构建如下(我对德语名称感到抱歉):

            <?xml version="1.0" encoding="UTF-8"?>

    <?import javafx.scene.layout.BorderPane?>
    <?import javafx.scene.control.TabPane?>
    <?import javafx.scene.control.Tab?>
    <?import javafx.scene.layout.FlowPane?>
    <?import javafx.scene.control.Button?>
    <?import javafx.scene.layout.AnchorPane?>
    <?import javafx.scene.layout.GridPane?>
    <?import javafx.scene.text.Text?>
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.control.TextField?>
    <?import javafx.scene.layout.ColumnConstraints?>
    <?import javafx.scene.control.RadioButton?>
    <?import javafx.scene.control.CheckBox?>

    <BorderPane  xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"  fx:controller="application.LeagueRulesController" >
        <center>
            <TabPane  tabClosingPolicy="UNAVAILABLE" >
                <tabs>
                    <Tab style="-fx-font-weight:bold" text="Liga Regeln" >
                        <AnchorPane  >
                            <children>
                                <GridPane AnchorPane.topAnchor="10.0" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" hgap="15" vgap="15" >
                                        <columnConstraints>
                                            <ColumnConstraints hgrow="ALWAYS" />
                                        </columnConstraints> 

                                    <children>
                                        <Label text="Anzahl der Zeichen im Teamnamen: " GridPane.columnIndex="0" GridPane.rowIndex="0"/>
                                        <TextField fx:id="numberOfShortNameChars" alignment="BASELINE_RIGHT" prefWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="0"/>

                                        <Label text="Anzahl der Touchdown Differenz Einträge: " GridPane.columnIndex="0" GridPane.rowIndex="1"/>
                                        <TextField fx:id="numberOfTDDiffEntries" alignment="BASELINE_RIGHT" prefWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="1"/>

                                        <GridPane fx:id="tdDiffEntrys" hgap="15" vgap="15" GridPane.columnIndex="1" GridPane.rowIndex="2" />

                                        <Label text="Erhält Gewinnerteam bei Spielaufgabe maximale Punktzahl?:" GridPane.columnIndex="0" GridPane.rowIndex="3"/>
                                        <CheckBox  fx:id="isConcedeMaxWin" GridPane.columnIndex="1" GridPane.rowIndex="3"></CheckBox>
                                    </children>
                                </GridPane>

                                <FlowPane  orientation="HORIZONTAL" alignment="BOTTOM_RIGHT" hgap="5" AnchorPane.topAnchor="10.0" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0">
                                    <Button fx:id="okButton" text="OK" onAction="#handleOK"> </Button>
                                    <Button fx:id="abbrechenButton" text="Abbrechen"  onAction="#handleAbbrechen"> </Button>                    
                                </FlowPane> 
                            </children>
                        </AnchorPane>
                    </Tab>
                    <Tab style="-fx-font-weight:bold" text="Teams verwalten">

                    </Tab>      
                </tabs>
            </TabPane>
        </center>
    </BorderPane>

虽然我确定问题可以在 .fxml 文件中找到,但我还添加了 LeagueRulesController class。

            package application;

    import java.net.URL;
    import java.util.ArrayList;
    import java.util.ResourceBundle;

    import javafx.beans.value.ChangeListener;
    import javafx.beans.value.ObservableValue;
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.geometry.Pos;
    import javafx.scene.control.Button;
    import javafx.scene.control.CheckBox;
    import javafx.scene.control.Label;
    import javafx.scene.control.TextField;
    import javafx.scene.layout.GridPane;
    import javafx.stage.Stage;

    public class LeagueRulesController implements Initializable{


        private ArrayList<TextField> tdDiffs;
        private ArrayList<TextField> points;



        @FXML
        private CheckBox isConcedeMaxWin;

        @FXML
        private Button okButton;
        @FXML
        private Button abbrechenButton;

        @FXML
        private void handleAbbrechen(ActionEvent actionEvet) {
            Stage stage = (Stage) abbrechenButton.getScene().getWindow();
            // do what you have to do
            stage.close();
        }

        @FXML
        private void handleOK(ActionEvent actionEvet) {

            Stage stage = (Stage) abbrechenButton.getScene().getWindow();
            stage.close();
        }

        @FXML
        private TextField numberOfShortNameChars;
        @FXML
        private TextField numberOfTDDiffEntries;    
        @FXML
        private GridPane tdDiffEntrys;

        @Override
        public void initialize(URL arg0, ResourceBundle arg1) {
            numberOfShortNameChars.setText("25");
            numberOfShortNameChars.textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    numberFieldListener(numberOfShortNameChars, oldValue,newValue);
                }
            });

            numberOfTDDiffEntries.setText("5");

            initializeTDDiffArray();

            numberOfTDDiffEntries.textProperty().addListener(new ChangeListener<String>() {

                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    numberFieldListener(numberOfTDDiffEntries, oldValue,newValue);
                    initializeTDDiffArray();
                }
            });
        }

        private void initializeTDDiffArray() {
            tdDiffEntrys.getChildren().clear();
            tdDiffs = new ArrayList<>();
            points = new ArrayList<>();

            tdDiffEntrys.add(new Label("TD Diff"), 0, 0);
            tdDiffEntrys.add(new Label("Punkte"), 1, 0);

            int numberOfTDDiffEntriesInt;
            if(numberOfTDDiffEntries.getText().equals(""))
                numberOfTDDiffEntriesInt = 1;
            else
                numberOfTDDiffEntriesInt =Integer.parseInt(numberOfTDDiffEntries.getText());

            for (int i = 0; i < numberOfTDDiffEntriesInt; i++) {
                tdDiffs.add(new TextField());
                points.add(new TextField());
                tdDiffs.get(tdDiffs.size()-1).setText(Integer.toString(i-numberOfTDDiffEntriesInt/2));
                points.get(points.size()-1).setText(Integer.toString(i+1));

                tdDiffs.get(tdDiffs.size()-1).setAlignment(Pos.BASELINE_RIGHT);
                points.get(points.size()-1).setAlignment(Pos.BASELINE_RIGHT);

                tdDiffs.get(tdDiffs.size()-1).setPrefWidth(1);
                points.get(points.size()-1).setPrefWidth(1);

                tdDiffs.get(tdDiffs.size()-1).textProperty().addListener(new ChangeListener<String>() {
                    @Override
                    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                        numberFieldListener(tdDiffs.get(tdDiffs.size()-1), oldValue,newValue);
                    }
                });
                points.get(points.size()-1).textProperty().addListener(new ChangeListener<String>() {
                    @Override
                    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                        numberFieldListener(points.get(points.size()-1), oldValue,newValue);
                    }
                });

                tdDiffEntrys.add(tdDiffs.get(tdDiffs.size()-1), 0, i+1);
                tdDiffEntrys.add(points.get(points.size()-1), 1,  i+1);
            }

        }

        private void numberFieldListener(TextField textField, String oldValue,String newValue) {

            if(!newValue.matches("\d*")) {
                textField.setText(newValue.replaceAll("[^\d]", ""));
            }
        }

    }

在此先感谢您抽出宝贵时间。

您的 FlowPane 在您的 GridPane 之上,这会阻止鼠标事件到达 GridPane。在您的 FXML 文件中,您将 AnchorPane 约束和 GridPaneFlowPane 设置为 10(对于顶部、左侧、底部和右侧).这意味着两个节点在 AnchorPane 中占用相同的 space。由于您添加了 FlowPane 第二个 GridPane 被覆盖。请注意,添加 GridPane 秒很可能允许您单击 TextField,但会阻止您单击 Button

而不是 AnchorPane 为什么不使用 VBox? A VBox is designed for laying out nodes vertically. You could also replace the FlowPane with an HBox 之类的东西,因为这似乎是您想要的行为。你最终会得到类似的东西:

<Tab>
    <VBox>
        <GridPane>
            <!-- your GirdPane children -->
        </GridPane>
        <HBox>
            <!-- your buttons -->
        </HBox>
    </VBox>
</Tab>

为简洁起见,我省略了属性。您显然会将它们设置为您想要的值.

如果你走这条路,你需要将你的 Label - 文本设置为 "Erhält Gewinnerteam bei Spielaufgabe maximale Punktzahl?:" - 移动到新的 HBox 作为第一个 child.这样它就与按钮保持一致。


当然,您没有来替换您的AnchorPane。如果你想保留它,你必须弄清楚如何让 FlowPane 的顶部锚点始终等于 GridPane 的底部距离顶部的距离。由于您当前将 GridPane 的顶部锚点设置为 10,因此 FlowPane 的顶部锚点必须类似于 10 + gridPaneHeight。我不确定您是否可以在 FXML 文件中执行此操作,这意味着您必须在控制器的初始化方法中执行此操作。如果您的应用程序要调整大小,您可能还必须在调整大小时更新顶部锚点。