我正在使用JavaFX开发一款扫雷游戏:
我的GridPane
是由ImageViews
组成的,我试图找到一种方法来计算在GridPane
上单击的图像的列和行索引。我目前有这个代码:
gameGrid.setOnMouseClicked(event -> //gameGrid is my GridPane
{
Node source = (Node)event.getSource();
int columnIndex = GridPane.getColumnIndex(source);
System.out.println(columnIndex);
int rowIndex = GridPane.getRowIndex(source);
if(event.getButton()== MouseButton.PRIMARY)
game.newRevealCell(columnIndex,rowIndex);
else if(event.getButton()==MouseButton.SECONDARY)
game.getGrid()[columnIndex][rowIndex].setFlagged(true);
//game.getGrid is a 2D array containing the game cells
});
但是,方法getClonIndex
和getRowIndex
返回null
。我做错了什么?
1感谢@trashgood提供的所有评论和答案。
但为了解决你的实际问题,我认为使用事件。getSource是问题的根本原因。事件返回的源始终是GridPane。
event.getTarget()方法将为您提供您单击的目标节点。所以我认为将其更改为getTarget()将解决您的问题。
下面是我的意思的工作演示。
更新:我错误地认为显式约束设置只能通过GridPane完成。添加方法。但是使用add/addRow/addColumn方法也会设置索引约束。
注意:如果你点击的目标节点是GridPane的直接子节点(在你的例子中),这将起作用。但是如果您的目标节点不是GridPane的直接子节点,比如StackPane有一个标签,如果您单击了该标签,就会抛出一个null异常。
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class GridPaneIndexingDemo extends Application {
@Override
public void start(Stage stage) throws Exception {
StackPane root = new StackPane();
Scene scene = new Scene(root, 450, 450);
stage.setScene(scene);
stage.setTitle("GridPane");
stage.show();
GridPane grid = new GridPane();
grid.setGridLinesVisible(true);
grid.addRow(0, getPane(1), getPane(2), getPane(3));
grid.addRow(1, getPane(4), getPane(5), getPane(6));
grid.addRow(2, getPane(7), getPane(8), getPane(9));
grid.setOnMouseClicked(event -> {
Node source = (Node) event.getTarget();
int columnIndex = GridPane.getColumnIndex(source);
int rowIndex = GridPane.getRowIndex(source);
System.out.println("Row : " + rowIndex + ", Col : " + columnIndex);
});
root.getChildren().add(grid);
}
private StackPane getPane(int i) {
String[] colors = {"grey", "yellow", "blue", "pink", "brown", "white", "silver", "orange", "lightblue", "grey"};
StackPane pane = new StackPane();
pane.setPrefSize(150,150);
pane.setStyle("-fx-background-color:" + colors[i] + ";-fx-border-width:2px;");
return pane;
}
public static void main(String[] args) {
Application.launch(args);
}
}
从这个例子开始,下面的变化用Button
的N
xN
实例填充GridPane
,将每个实例添加到List
每个网格按钮如何知道自己在网格中的位置?每个按钮都有自己的匿名类实例——按钮的事件处理程序——它可以访问传递给
createGridButton()
的行和列参数。这些参数实际上是最终的;相比之下,使用早期版本的Java的原始示例必须显式地使参数最终。
虽然这种方法获取网格中任何
来获得所需的外观。Node
的行和列,但在该上下文中,Button
或TokgleButton
可能更方便。特别是,您可以使用带有ContentDisplay.GRAPHIC_ONLY
的setGrapics()
另一方面,GridPane
方法getColumnIndex
和getRowIndex
仅在设置时返回null
,因为它们引用子级的索引约束。
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
/** @see https://stackoverflow.com/a/69429741/230513 */
public class GridButtonTest extends Application {
private static final int N = 5;
private final List<Button> list = new ArrayList<>();
private Button getGridButton(int r, int c) {
int index = r * N + c;
return list.get(index);
}
private Button createGridButton(int row, int col) {
Button button = new Button("r" + row + ",c" + col);
button.setOnAction((ActionEvent event) -> {
System.out.println(event.getSource() == getGridButton(row, col));
});
return button;
}
@Override
public void start(Stage stage) {
stage.setTitle("GridButtonTest");
GridPane root = new GridPane();
for (int i = 0; i < N * N; i++) {
int row = i / N;
int col = i % N;
Button gb = createGridButton(row, col);
list.add(gb);
root.add(gb, row, col);
GridPane.setMargin(gb, new Insets(N));
}
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
对于使用二维数组的模型,也考虑List
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
/** @see https://stackoverflow.com/a/69429741/230513 */
public class GridButtonTest extends Application {
private static final int N = 5;
private final List<List<Button>> list = new ArrayList<>();
private Button getGridButton(int r, int c) {
return list.get(r).get(c);
}
private Button createGridButton(int row, int col) {
Button button = new Button("r" + row + ",c" + col);
button.setOnAction((ActionEvent event) -> {
System.out.println(event.getSource() == getGridButton(row, col));
});
return button;
}
@Override
public void start(Stage stage) {
stage.setTitle("GridButtonTest");
GridPane root = new GridPane();
for (int row = 0; row < N; row++) {
list.add(new ArrayList<>());
for (int col = 0; col < N; col++) {
Button gb = createGridButton(row, col);
list.get(row).add(gb);
root.add(gb, row, col);
GridPane.setMargin(gb, new Insets(N));
}
}
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
好吧,这是一个棘手的问题,这几天来一直让我抓狂... 作为users admin阶段(参见elements hierarchy)上方锚定窗格的滚动窗格的子窗格,我在UsersAdminController初始化期间添加了一个GridPane,该GridPane用于列出系统的用户(如本文所述)。当我通过user addition屏幕添加用户时,我尝试通过获取对UsersAdminController
我有一个学校项目或类似的东西,我试图为用户制作一个注册面板。当用户点击注册时,这个面板会打开。它看起来像这样。 我想做的是禁用创建按钮,只有在对话框上有3个检查时才会启用。 我在对话框上使用GridPane,我在考虑返回这些单元格上的某些节点(检查是图像视图),并检查条件是否为真。然而,我不知道如何从GridPane返回节点。如果你有其他方法来解决这个问题,也没关系。 这是代码的相关部分。
我是JavaFx新手,我在FXMl中创建了两个gridPane,我想用JavaFx做同样的事情。 我想创建一个扩展GridPane的类,所以当我调用我的类时,我将得到与fxml PS中相同的结果:如果您使用的是SceneBuilder,请检查网格线是否可见,以便可以看到所有GridPane谢谢
我正在用JavaFX编写一个益智游戏。 您可以在单击网格后与另一个按钮进行按钮交换吗? 前任。我想在按下按钮1后交换按钮1和9。我认为应该有可能改变网格窗格的位置。 当我点击按钮4时,它与按钮9互换。 有没有办法做到这一点? 这是我的代码:
我打算再试一次。。。我是Scenebuilder的新手,我正在尝试为我的项目创建一个照片库!我已经添加了我想要的,那就是一个图像视图,其中的图像是从FileChooser中选择的。。。但是现在我想得到一个建议,如何保存这个,并在每次按下addPhoto按钮时创建一个新的,而不是覆盖我在ImageView中已经有的。以下是我的addPhoto按钮代码: FXML代码:
主要内容:示例,示例2GridPane通常用于布局:第一列上的只读标签的输入表单和第二列上的输入字段。 GridPane可以在行,列或单元格级别指定约束。 例如,我们可以设置包含输入文本字段的第二列,以在窗口调整大小时调整大小。 示例 以下代码演示使用GridPane布局的简单表单应用程序。它有以下布局。 完整的代码实现如下所示 - 上面的代码生成以下结果。 示例2 以下是一个实现登录窗口的代码 - 上面的代码生成以下