GridPane per Maus Zelle bekommen, wie?

javaRekrut

Mitglied
Liebe Mitglieder,

Ich habe eine GridPane 8x8 (in ScenenBuilder, aber das sollte keine Rolle spielen) erstellt. Ich möchte per Mausklick auf eines dieser Felder (Zelle) den Zellenindex(Reihe,Spalte) auf der Konsole angezeigt bekommen. Meine bisherigen Recherchen im Netz sind leider nicht geglückt.

Die bisher sinnvollste Methode in meinen Augen aus dem Netz ist diese:

@FXML
private void mouseEntered(MouseEvent e) {
Node source = (Node)e.getSource() ;
Integer colIndex = GridPane.getColumnIndex(source);
Integer rowIndex = GridPane.getRowIndex(source);
System.out.printf("Mouse entered cell [%d, %d]%n", colIndex.intValue(), rowIndex.intValue());
}

Beim Testen erhalte ich jedoch einen NullPointerException. Auch beim Test des Objekts an sich "System.out.println(colIndex);" erhalte ich 'null'.

Ich hoffe ich habe genügend Informationen zu meinem Hindernis geschildert, ansonsten liefer ich nach.

Danke im voraus 🙂
 
Es gibt wirklich keine echte API dafür, da das GridPane ein Layout ist und keine echte Tabelle.
Erinnere mich morgen mal und ich baue ein kleines Beispiel, wir man es dennoch irgendwie zustande bringt...
 
Hoi zäme

Hier mal meine Idee, wie man so etwas machen kann. Nicht schön, aber gibt am Ende dir Element und Spalte/Zeile aus.
Java:
package eu.dzim.tests.fx;

import java.util.Locale;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class MainGridSelect extends Application {
   
    private final Class<?>[] availableNodes = new Class<?>[] { Label.class, Button.class, CheckBox.class, HBox.class };
    private final Random random = new Random(System.currentTimeMillis());
    private final Pattern pattern = Pattern.compile("item_(\\d+)_(\\d+)");
   
    @Override
    public void start(Stage stage) throws Exception {
       
        stage.setTitle("Grid Select");
       
        GridPane root = buildContent();
        Scene scene = new Scene(root, 1200, 800);
        initialize(stage, scene, root);
       
        stage.setScene(scene);
        stage.show();
    }
   
    private GridPane buildContent() {
        GridPane pane = new GridPane();
       
        pane.setHgap(5.0);
        pane.setVgap(5.0);
       
        final int max = 4;
        for (int i = 0; i < max; i++) {
            for (int j = 0; j < max; j++) {
                Node n = getRandomNode(pane, max, i, j);
                GridPane.setConstraints(n, i, j);
                pane.getChildren().add(n);
            }
        }
       
        return pane;
    }
   
    private Node getRandomNode(GridPane pane, int max, int i, int j) {
       
        int r = random.nextInt(max);
        Class<?> clazz = availableNodes[r];
       
        Node n;
        if (Label.class.isAssignableFrom(clazz)) {
            n = new Label(String.format(Locale.ROOT, "%d, %d", i, j));
        } else if (Button.class.isAssignableFrom(clazz)) {
            n = new Button(String.format(Locale.ROOT, "%d, %d", i, j));
        } else if (CheckBox.class.isAssignableFrom(clazz)) {
            n = new CheckBox(String.format(Locale.ROOT, "%d, %d", i, j));
        } else if (HBox.class.isAssignableFrom(clazz)) {
            n = new HBox();
            ((HBox) n).setSpacing(5.0);
            Label l = new Label("" + i);
            l.setOnMouseClicked(e -> pane.fireEvent(e.copyFor(n, pane)));
            Button b = new Button("" + j);
            b.setOnMouseClicked(e -> pane.fireEvent(e.copyFor(n, pane)));
            ((HBox) n).getChildren().addAll(l, b);
        } else {
            return null;
        }
        n.setId("item_" + i + "_" + j);
        n.setOnMouseClicked(e -> pane.fireEvent(e.copyFor(n, pane)));
        return n;
    }
   
    private void initialize(Stage stage, Scene scene, GridPane pane) {
        pane.setOnMouseClicked(e -> {
            pane.getChildren().stream()
                    .filter(n -> n.getLayoutX() <= e.getX() && e.getX() <= (n.getLayoutX() + n.getLayoutBounds().getWidth())
                            && n.getLayoutY() <= e.getY() && e.getY() <= (n.getLayoutY() + n.getLayoutBounds().getHeight()))
                    .forEach(n -> handleClick(e, n));
        });
    }
   
    private void handleClick(MouseEvent e, Node targetNode) {
        System.err.println(targetNode);
        String id = targetNode.getId();
        if (id != null) {
            Matcher m = pattern.matcher(id);
            if (m.matches()) {
                String colString = m.group(1);
                String rowString = m.group(2);
                System.err.printf("Grid element: Column=%s, Row=%s", colString, rowString);
            }
        }
    }
   
    public static void main(String[] args) {
        launch(args);
    }
}

Aber Achtung: Der Ansatz ist stark limitiert: Es fängt dann an frimelig zu werden, wenn du statt Labels/Buttons weitere Layouts mit Komponenten darauf verwendest.
Denn generell musst du die Events weiter propagieren, dass macht es unnötig kompliziert.

Grüsse,
Daniel
 
Danke für eure Hilfe!
Ich habe eine andere Möglichkeit gefunden um mein Projekt zu realisieren. Habe eigene Tabelle 8x8 erstellt welches aus Rectangle mit events besteht.

Funktioniert wunderbar. Danke nochmals 🙂
 

Neue Themen


Zurück
Oben