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
约束和 GridPane
和 FlowPane
设置为 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 文件中执行此操作,这意味着您必须在控制器的初始化方法中执行此操作。如果您的应用程序要调整大小,您可能还必须在调整大小时更新顶部锚点。
我想做什么?
我遇到了基于 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
约束和 GridPane
和 FlowPane
设置为 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 文件中执行此操作,这意味着您必须在控制器的初始化方法中执行此操作。如果您的应用程序要调整大小,您可能还必须在调整大小时更新顶部锚点。