2

Currently there are 2 sets of grids. the first gridset is a 5x4 grid which has images of the map. On top of that, there's a grid which has all of the small tiles to each of the 5x4 grid boxes.

Example Grid Image

So I need to have large images in a 5x4 grid pattern, with 16x16 mini tiles within each of those tiles, and each mini tile needs to be paintable (or have images) above the underlying image which exists in the large acres.

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

<?import java.lang.String?>
<?import java.net.URL?>
<?import javafx.collections.FXCollections?>
<?import javafx.scene.canvas.Canvas?>
<?import javafx.scene.control.Accordion?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.StackPane?>

<BorderPane id="mainPane" fx:id="editorPane" prefHeight="500.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/null" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.michaelgatesdev.OldLeaf.gui.controllers.tabs.TabMapEditorController">

    <stylesheets>
        <URL value="@../../css/tabs/TabMapEditor.css"/>
        <URL value="@../../css/Flat.css"/>
        <URL value="@../../css/FlatColors.css"/>
    </stylesheets>

    <center>
        <ScrollPane id="map-editor-grid-container" fx:id="gridContainer" fitToHeight="true" fitToWidth="true" nodeOrientation="LEFT_TO_RIGHT" styleClass="content-pane">
            <content>
                <StackPane fx:id="stackPane">
                    <children>
                        <GridPane id="map-editor-grid-acres" fx:id="gridAcres">
                            <columnConstraints>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="192.0" minWidth="192.0" prefWidth="192.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="192.0" minWidth="192.0" prefWidth="192.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="192.0" minWidth="192.0" prefWidth="192.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="192.0" minWidth="192.0" prefWidth="192.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="192.0" minWidth="192.0" prefWidth="192.0"/>
                            </columnConstraints>
                            <rowConstraints>
                                <RowConstraints maxHeight="192.0" minHeight="192.0" prefHeight="192.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="192.0" minHeight="192.0" prefHeight="192.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="192.0" minHeight="192.0" prefHeight="192.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="192.0" minHeight="192.0" prefHeight="192.0" vgrow="ALWAYS"/>
                            </rowConstraints>
                        </GridPane>
                        <GridPane id="map-editor-grid-tiles" fx:id="gridTiles">
                            <columnConstraints>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                                <ColumnConstraints hgrow="ALWAYS" maxWidth="12.0" minWidth="12.0" prefWidth="12.0"/>
                            </columnConstraints>
                            <rowConstraints>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                                <RowConstraints maxHeight="12.0" minHeight="12.0" prefHeight="12.0" vgrow="ALWAYS"/>
                            </rowConstraints>
                        </GridPane>
                    </children>
                </StackPane>
            </content>
        </ScrollPane>
    </center>
    <left>
        <AnchorPane id="map-editor-tools-container" fx:id="toolsPane" prefHeight="200.0" prefWidth="200.0" styleClass="content-pane" BorderPane.alignment="CENTER">
            <children>
                <HBox id="map-editor-tools-search-pane" fx:id="toolsSearchPane" alignment="CENTER" prefHeight="50.0" prefWidth="200.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="00.0">
                    <children>
                        <ComboBox id="map-editor-tools-search" fx:id="toolsSearch" editable="true" prefHeight="25.0" prefWidth="185.0" promptText="Search.." styleClass="flat-combo-box"/>
                    </children>
                </HBox>
                <ScrollPane id="map-editor-tools-list-pane" fx:id="toolsListPane" fitToHeight="true" fitToWidth="true" prefHeight="328.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="50.0">
                    <content>
                        <Accordion id="map-editor-tools-accordion" fx:id="toolsAccordion" prefWidth="185.0" styleClass="flat-accordion">
                            <panes>
                                <TitledPane animated="true" text="Empty">
                                    <content>
                                        <ListView prefHeight="200.0" prefWidth="200.0">
                                            <items>
                                                <FXCollections fx:factory="observableArrayList">
                                                    <String fx:value="Blank (0x00)"/>
                                                </FXCollections>
                                            </items>
                                        </ListView>
                                    </content>
                                </TitledPane>
                            </panes>
                        </Accordion>
                    </content>
                </ScrollPane>
            </children>
        </AnchorPane>
    </left>
</BorderPane>

As you can see, the FXML is very messy and just overall feels unnecessary.

So my question is: How can I draw all of this, using as few grids or none if possible, while still allowing me access to the grid tiles (column,row,data,etc) through some convenient bean component?

Michael Gates
  • 107
  • 1
  • 12

2 Answers2

6

Create a custom paintable grid component and lay it over the images.

Code

Main.java

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.PickResult;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application {

    boolean showHoverCursor = true;

    int rows = 15;
    int columns = 20;
    double width = 800;
    double height = 600;

    ImageView imageView = new ImageView( new Image( "https://upload.wikimedia.org/wikipedia/commons/c/c7/Pink_Cat_2.jpg"));


    @Override
    public void start(Stage primaryStage) {
        try {
            StackPane root = new StackPane();

            // create grid
            Grid grid = new Grid( columns, rows, width, height);

            MouseGestures mg = new MouseGestures();

            // fill grid
            for (int row = 0; row < rows; row++) {
                for (int column = 0; column < columns; column++) {

                    Cell cell = new Cell(column, row);

                    mg.makePaintable(cell);

                    grid.add(cell, column, row);
                }
            }

            root.getChildren().addAll(imageView, grid);

            // create scene and stage
            Scene scene = new Scene(root, width, height);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();



        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

    private class Grid extends Pane {

        int rows;
        int columns;

        double width;
        double height;

        Cell[][] cells;

        public Grid( int columns, int rows, double width, double height) {

            this.columns = columns;
            this.rows = rows;
            this.width = width;
            this.height = height;

            cells = new Cell[rows][columns];

        }

        /**
         * Add cell to array and to the UI.
         */
        public void add(Cell cell, int column, int row) {

            cells[row][column] = cell;

            double w = width / columns;
            double h = height / rows;
            double x = w * column;
            double y = h * row;

            cell.setLayoutX(x);
            cell.setLayoutY(y);
            cell.setPrefWidth(w);
            cell.setPrefHeight(h);

            getChildren().add(cell);

        }

        public Cell getCell(int column, int row) {
            return cells[row][column];
        }

        /**
         * Unhighlight all cells
         */
        public void unhighlight() {
            for( int row=0; row < rows; row++) {
                for( int col=0; col < columns; col++) {
                    cells[row][col].unhighlight();
                }
            }
        }
    }

    private class Cell extends StackPane {

        int column;
        int row;

        public Cell(int column, int row) {

            this.column = column;
            this.row = row;

            getStyleClass().add("cell");

//          Label label = new Label(this.toString());
//
//          getChildren().add(label);

            setOpacity(0.9);
        }

        public void highlight() {
            // ensure the style is only once in the style list
            getStyleClass().remove("cell-highlight");

            // add style
            getStyleClass().add("cell-highlight");
        }

        public void unhighlight() {
            getStyleClass().remove("cell-highlight");
        }

        public void hoverHighlight() {
            // ensure the style is only once in the style list
            getStyleClass().remove("cell-hover-highlight");

            // add style
            getStyleClass().add("cell-hover-highlight");
        }

        public void hoverUnhighlight() {
            getStyleClass().remove("cell-hover-highlight");
        }

        public String toString() {
            return this.column + "/" + this.row;
        }
    }

    public class MouseGestures {

        public void makePaintable( Node node) {


            // that's all there is needed for hovering, the other code is just for painting
            if( showHoverCursor) {
                node.hoverProperty().addListener(new ChangeListener<Boolean>(){

                    @Override
                    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {

                        System.out.println( observable + ": " + newValue);

                        if( newValue) {
                            ((Cell) node).hoverHighlight();
                        } else {
                            ((Cell) node).hoverUnhighlight();
                        }

                        for( String s: node.getStyleClass())
                            System.out.println( node + ": " + s);
                    }

                });
            }

            node.setOnMousePressed( onMousePressedEventHandler);
            node.setOnDragDetected( onDragDetectedEventHandler);
            node.setOnMouseDragEntered(onMouseDragEnteredEventHandler);

        }

        EventHandler<MouseEvent> onMousePressedEventHandler = event -> {

            Cell cell = (Cell) event.getSource();

            if( event.isPrimaryButtonDown()) {
                cell.highlight();
            } else if( event.isSecondaryButtonDown()) {
                cell.unhighlight();
            }
        };

        EventHandler<MouseEvent> onMouseDraggedEventHandler = event -> {

            PickResult pickResult = event.getPickResult();
            Node node = pickResult.getIntersectedNode();

            if( node instanceof Cell) {

                Cell cell = (Cell) node;

                if( event.isPrimaryButtonDown()) {
                    cell.highlight();
                } else if( event.isSecondaryButtonDown()) {
                    cell.unhighlight();
                }

            }

        };

        EventHandler<MouseEvent> onMouseReleasedEventHandler = event -> {
        };

        EventHandler<MouseEvent> onDragDetectedEventHandler = event -> {

            Cell cell = (Cell) event.getSource();
            cell.startFullDrag();

        };

        EventHandler<MouseEvent> onMouseDragEnteredEventHandler = event -> {

            Cell cell = (Cell) event.getSource();

            if( event.isPrimaryButtonDown()) {
                cell.highlight();
            } else if( event.isSecondaryButtonDown()) {
                cell.unhighlight();
            }

        };

    }

}

application.css

.cell {
    -fx-border-color: dodgerblue;
    -fx-border-width: 1px;
}
.cell-highlight {
    -fx-background-color:derive(dodgerblue,0.9);
}
.cell-hover-highlight {
    -fx-background-color:derive(green,0.9);
}

Screenshot

enter image description here

Roland
  • 18,114
  • 12
  • 62
  • 93
  • This is exactly what I am looking for! Unfortunately I can't do this solely in FXML which I'd like to do, but there just isn't enough support behind custom components at the moment, I guess. Question: In my picture, I also have boldened the 5x4 map grid tile lines by just using another grid. Is there a way to do that on this as well without manually painting every line/rectangle? – Michael Gates Apr 02 '16 at 06:17
  • Just modfiy the [CSS](https://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html) for that purpose. No need to "draw" anything. – Roland Apr 02 '16 at 06:23
  • I ended up lying another grid over it because I couldn't figure out the CSS for it. I'm having an issue, though. It's taking an awful long time to draw the grid and I have a strong pc rig. The reason is because each cell is making unnecessary draw calls. The first box renders 4 lines, the second box should only have to render a bottom, right, top, same with the rest of the row. The next row shouldn't have to render a top since it's already been rendered. How can I avoid all the unnecessary draw calls? – Michael Gates May 16 '16 at 19:56
0

Here's what I went with.

Essentially I scrapped the FXML grid because it was terribly slow for what I was trying to do. In its place, I created a custom canvas and drew my own grid lines. This was great because it allowed me to draw multiple layers and still be tenfold faster than the FX solution. For a rough reference, the FX solution took ~2 full minutes to draw a single grid, the Canvas solution takes about ~75ms to draw 3 canvases.

Michael Gates
  • 107
  • 1
  • 12