簡體   English   中英

JavaFX:在 GridPane 單擊更新 ImageView

[英]JavaFX: Update ImageView on GridPane click

我正在使用 JavaFX 開發掃雷游戲:

(游戲開始時)

我的GridPaneImageViews組成,我試圖找到一種方法來找出在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

});

但是,方法getColumnIndexgetRowIndex返回null 我究竟做錯了什么?

從這個例子開始,下面的變體用ButtonN x N實例填充GridPane ,將每個實例添加到List<Button> 方法getGridButton()顯示了如何根據其網格坐標有效地獲取按鈕引用,並且動作偵聽器顯示單擊和找到的按鈕是相同的。

每個網格按鈕如何知道自己在網格上的位置? 每個都有自己的匿名類實例——按鈕的事件處理程序——可以訪問傳遞給createGridButton()的行和列參數。 這些參數實際上是最終的; 相比之下,使用早期版本的 Java 的原始示例必須明確地使參數成為最終參數。

雖然此方法獲取網格中任何Node的行和列,但ButtonToggleButton在此上下文中可能更方便。 特別是,您可以將setGraphic()ContentDisplay.GRAPHIC_ONLY結合使用以獲得所需的外觀。

順便說一句, GridPane方法getColumnIndexgetRowIndex返回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, col, row);
            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<List<Button>> ,如下所示:

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, col, row);
                GridPane.setMargin(gb, new Insets(N));
            }
        }
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

+1 對於@trashgod 提供的所有評論和答案。

但試圖解決您的實際問題,我認為使用 event.getSource 是您問題的根本原因。 從事件返回的源將始終是 GridPane。

event.getTarget() 方法將為您提供您單擊的目標節點。 所以我認為將其更改為 getTarget() 將解決您的問題。

下面是我的意思的工作演示。 即使我沒有顯式設置索引約束,這也有效

更新:我誤認為顯式約束設置只能通過 GridPane.add 方法完成。 但是使用 add/addRow/addColumn 方法也會設置索引約束。

注意:如果您單擊的目標節點是 GridPane 的直接子節點(在您的情況下),這將起作用。 但是,如果您的目標節點不是 GridPane 的直接子節點,例如 StackPane 有一個標簽,並且如果您單擊該標簽,則會拋出空異常。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM