【问题标题】:How to add edges to gridpane如何将边缘添加到网格窗格
【发布时间】:2022-01-05 21:02:36
【问题描述】:

我正在努力编写一个程序,该程序需要我使用 GUI 和 MVC 设计模式制作 nonogram 游戏。由于它是一个非图游戏,我需要创建一个网格。一个非图游戏应该是这样的:

这是我在 GridPane 中创建矩形得到的结果:

但我不知道如何在我创建的网格窗格周围添加包含游戏线索的边缘。

这是我的代码:

public class PuzzleView implements FXComponent {

  private Controller controller;
  Model model;

  public PuzzleView(Controller controller) {
    this.controller = controller;
    model = ((ControllerImpl) controller).getModel();
  }
So
  @Override
  public Parent render() {

    GridPane board = new GridPane();
    double width = 30;
    board.setLayoutX(300);
    board.setLayoutY(300);
    int h = model.getHeight();
    int w = model.getWidth();

    Rectangle[][] rec = new Rectangle[w][h];

    for (int i = 0; i < w; i++) {
      for (int j = 0; j < h; j++) {
        rec[i][j] = new Rectangle();
        rec[i][j].setX(i * width);
        rec[i][j].setY(j * width);
        rec[i][j].setWidth(width);
        rec[i][j].setHeight(width);
        rec[i][j].setFill(Color.WHITE);
        rec[i][j].setStroke(Color.BLACK);
        board.add(rec[i][j], i, j);
      }
    }

【问题讨论】:

  • 在我的脑海中(必须真正使用 JavaFX),您应该使用复合布局。也就是说,您使用一个父容器,它在包含GridPane 的容器周围布置“提示”,也许使用BorderPane?然后,BorderPane 的每个边缘都可以根据您的需要包含不同的布局窗格
  • 首先,将board.add(rec[i][j], i, j) 更改为board.add(rec[i][j], i + 1, j + 1)。然后您可以将“线索”框添加到第 0 行和第 0 列。

标签: java user-interface javafx model-view-controller


【解决方案1】:

考虑使用 JavaFX Control(或 Pane)而不是 shape 来表示网格单元,并使用 4 个 GridPanes 来表示板的不同区域:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.control.Label;
import javafx.scene.layout.*;
import javafx.stage.Stage;

public class MonogramBoard extends Application {

    private static final int BOARD_SIZE = 5, HINT_SIZE = 2;

    @Override
    public void start(Stage primary) {
        Node corner = new Board(HINT_SIZE, HINT_SIZE, false, false).getNode();
        Node topHint = new Board(HINT_SIZE, BOARD_SIZE, true, true).getNode();
        HBox topPane = new HBox(corner, topHint);

        Node leftHint =  new Board(BOARD_SIZE,HINT_SIZE, true, true).getNode();
        Node board = new Board(BOARD_SIZE, BOARD_SIZE, true, true).getNode();
        HBox bottomPane = new HBox(leftHint, board);
        VBox root = new VBox(topPane, bottomPane);
        root.setPadding(new Insets(10));
        primary.setScene(new Scene(root));
        primary.show();
    }

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

class Board{
    private final GridPane grid;

    public Board(int rows, int columns, boolean isBorder, boolean isGridLines) {
        grid = new GridPane();
        grid.setPadding(new Insets(1));
        if(isBorder) {
            grid.setStyle("-fx-background-color: white; -fx-border-color: black ; -fx-border-width: 2px");
        }else{
            grid.setStyle("-fx-background-color: white; -fx-border-color: white ; -fx-border-width: 2px");
        }
        for(int row = 0; row < rows; row++){
            for(int col = 0; col < columns; col++){
                grid.add(new Cell(isGridLines).getNode(), col, row);
            }
        }
    }

    Node getNode() {return grid; }
}

//represents a single cell
class Cell{
    private final Label label;
    private final int CELL_SIZE = 50;

    Cell(){
        this(true);
    }

    Cell(boolean isBorder){

        label = new Label();
        if(isBorder) {
            label.setStyle("-fx-background-color: white; -fx-border-color: black ; -fx-border-width: 1px");
        }else{
            label.setStyle("-fx-background-color: white; -fx-border-color: white ; -fx-border-width: 1px");
        }
        label.setPrefSize(CELL_SIZE,CELL_SIZE);
    }

    Node getNode() {return label; }
}

【讨论】:

    【解决方案2】:

    在布局方面,将有不止一种方法来解决它。您可以选择 cmets 中建议的方式,也可以使用以下方法。

    以下方法依赖于使用 CSS 设置边框样式。通过这种方式,您可以准确地获得您所期望的外观,并且还可以完美地适用于任何尺寸的电路板。

    首先,您将提示部分和拼图部分分成单独的网格窗格。这样您就可以更好地控制各个部分。

    然后您在网格窗格中设置网格窗格和框的样式以获得所需的样式。在第二个屏幕截图中,我添加了间距以展示每个网格窗格和框的样式以实现最终外观。

    关键是您要专门设置每个边框的边宽(0px、1px 或 2px)。渲染最终布局后,您将获得所需的外观。

    请查看以下演示:

    import javafx.application.Application;
    import javafx.geometry.Insets;
    import javafx.scene.Scene;
    import javafx.scene.control.CheckBox;
    import javafx.scene.layout.GridPane;
    import javafx.scene.layout.StackPane;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    
    import java.util.stream.Stream;
    
    public class GridPaneBordersDemo extends Application {
        @Override
        public void start(Stage stage) throws Exception {
             double width = 30; // each box size
            int rows = 8; // Main box rows & cols
            int cols = 6;
            int topHintRows = 3;
            int sideHintCols = 4;
    
            // Top hint pane
            GridPane topHint = new GridPane();
            topHint.getStyleClass().add("topHintPane");
            for (int i = 0; i < cols; i++) {
                for (int j = 0; j < topHintRows; j++) {
                    StackPane box = getBox(width);
                    box.getStyleClass().add("topHintBox");
                    topHint.add(box, i, j);
                }
            }
    
            // Side hint pane
            GridPane sideHint = new GridPane();
            sideHint.getStyleClass().add("sideHintPane");
            for (int i = 0; i < sideHintCols; i++) {
                for (int j = 0; j < rows; j++) {
                    StackPane box = getBox(width);
                    box.getStyleClass().add("sideHintBox");
                    sideHint.add(box, i, j);
                }
            }
    
            // Main Puzzle
            GridPane mainPuzzle = new GridPane();
            mainPuzzle.getStyleClass().add("puzzlePane");
            for (int i = 0; i < cols; i++) {
                for (int j = 0; j < rows; j++) {
                    StackPane box = getBox(width);
                    box.getStyleClass().add("puzzleBox");
                    mainPuzzle.add(box, i, j);
                }
            }
    
            GridPane emptyGrid = new GridPane();
            emptyGrid.getStyleClass().add("emptyGrid");
    
            GridPane pane = new GridPane();
            pane.setPadding(new Insets(10));
            pane.add(emptyGrid,0,0);
            pane.add(topHint,1,0);
            pane.add(sideHint,0,1);
            pane.add(mainPuzzle,1,1);
    
            CheckBox checkBox = new CheckBox("Show spacing");
            checkBox.selectedProperty().addListener((obs,old,val)->{
                double gap = val?10:0;
                Insets insets = val? new Insets(10):Insets.EMPTY;
                Stream.of(pane,topHint,sideHint,mainPuzzle,emptyGrid).forEach(grid->{
                    grid.setHgap(gap);
                    grid.setVgap(gap);
                    grid.setPadding(insets);
                });
                stage.sizeToScene();
            });
            VBox root =new VBox(checkBox,pane);
            root.setSpacing(10);
            root.setPadding(new Insets(10));
            Scene scene = new Scene(root);
            scene.getStylesheets().add(getClass().getResource("grid.css").toExternalForm());
            stage.setScene(scene);
            stage.setTitle("GridPane Border");
            stage.setOnShown(e->stage.sizeToScene());
            stage.show();
    
        }
    
        private StackPane getBox(double width){
            StackPane box = new StackPane();
            box.setMinSize(width,width);
            box.setMaxSize(width,width);
            box.getStyleClass().add("box");
            return box;
        }
    }
    

    CSS 代码(grid.css):

    .emptyGrid{
       -fx-border-width: 0px 1px 1px 0px;
       -fx-border-color: black;
    }
    
    .topHintPane{
       -fx-border-width: 2px 1px 1px 1px;
       -fx-border-color: black;
    }
    
    .sideHintPane{
       -fx-border-width: 1px 1px 1px 2px;
       -fx-border-color: black;
    }
    
    .puzzlePane{
       -fx-border-width: 1px;
       -fx-border-color: black;
    }
    
    .box{
      -fx-background-color:transparent ;
    }
    
    .topHintBox{
       -fx-border-width: 0px 1px 0px 0px;
       -fx-border-color: black;
    }
    
    .sideHintBox{
       -fx-border-width: 0px 0px 1px 0px;
       -fx-border-color: black;
    }
    
    .puzzleBox{
       -fx-border-width: 0px 1px 1px 0px;
       -fx-border-color: black;
    }
    

    我再次提醒您,您也可以通过其他方法实现。这只是使用单个框和 gridPane 样式的一种方式。

    【讨论】:

      猜你喜欢
      • 2014-01-20
      • 2014-10-12
      • 1970-01-01
      • 2017-04-26
      • 1970-01-01
      • 2020-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多