java—某些组件在javafx中堆叠在一起

fbcarpbf  于 2021-07-12  发布在  Java
关注(0)|答案(3)|浏览(371)

我想建立一个类似这样的非图

但目前我的代码显示的线索(顶部和左侧的数字)是这样的

当我想把线索排成一行的时候,这些线索是叠在一起的。
这是我目前使用javafx的代码:

public class PuzzleView implements FXComponent {

  private Controller controller;
  private Pane board;
  private Pane entirePuzzle;
  private VBox[] vertClues;
  private HBox[] horzClues;
  private Pane[][] tiles;

  public PuzzleView(Controller controller) {
    this.controller = controller;
  }

  @Override
  public Parent render() {
    entirePuzzle = new Pane(); // grid pane
    initBoard();
    initLabels();
    entirePuzzle.getChildren().add(board);
    return entirePuzzle;
  }

  private void initBoard() {
    board = new Pane();
    int width = controller.getClues().getWidth();
    int height = controller.getClues().getHeight();
    board.setLayoutX(100);
    board.setLayoutY(100);
    for (int i=0; i<2; i++) {
      for (int j=0; j<2; j++) {
        Rectangle clues = new Rectangle();
        clues.setWidth(width);
        clues.setHeight(height);
        clues.setLayoutX(i*(width*50));
        clues.setLayoutY(j*height*50);
        clues.setStroke(Color.LIGHTBLUE);
        clues.setStrokeWidth(2);
        clues.setFill(Color.WHITE);
        board.getChildren().add(clues);
      }
    }

    tiles = new Pane[width][height];
    for (int i=0; i<width; i++) {
      for (int j=0; j<height; j++) {
        tiles[i][j] = new Pane();
        Rectangle rect = new Rectangle(50, 50);
        rect.setStroke(Color.LIGHTGRAY);
        rect.setStrokeWidth(1);
        rect.setFill(Color.TRANSPARENT);
        tiles[i][j].getChildren().add(rect);
        tiles[i][j].setLayoutX(i*50);
        tiles[i][j].setLayoutY(j*50);
        board.getChildren().add(tiles[i][j]);
      }
    }
  }

  private void initLabels() {
    int width = controller.getClues().getWidth();
    int height = controller.getClues().getHeight();
    vertClues = new VBox[height];
    horzClues = new HBox[width];
    Clues clue = controller.getClues();
    for (int i = 0; i < width; i++) {
      horzClues[i] = new HBox();
      horzClues[i].setLayoutX(100 + i * width);

      for (int j=0; j<controller.getClues().getColCluesLength(); j++) {
        horzClues[i].setSpacing(width);
        Label label = new Label(String.valueOf(clue.getColClues(i)[j]));
        label.minHeight(25);
        label.minWidth(25);
        horzClues[i].getChildren().add(label);
      }

      entirePuzzle.getChildren().add(horzClues[i]);

    }

    for (int i = 0; i < height; i++) {
      vertClues[i] = new VBox();
      vertClues[i].setLayoutY(100 + i * height);
      for (int j=0; j<controller.getClues().getRowCluesLength(); j++) {
        Label label = new Label(String.valueOf(clue.getRowClues(i)[j]));
        label.minHeight(25);
        label.minWidth(25);
        vertClues[i].getChildren().add(label);
      }

      entirePuzzle.getChildren().add(vertClues[i]);
    }
  }
}
``` `FXComponent` 是我做的一个界面 `render()` 方法返回一个组件对象,我可以将其放在不同的类中。 `controller` 是我创建的另一个类,它允许我访问拼图本身的属性和其他函数。
nkcskrwz

nkcskrwz1#

不是一个完整的答案,只是一个建议,但希望它能帮助你进步。
我建议使用瓷砖板的董事会,其中每个“瓷砖”是一个切换按钮。有关更改按钮颜色的方法,请参阅javafx中的按钮颜色更改 ToggleButton .
以“板”为中心 Node 并将行提示放在左侧 Node 列提示为顶部 Node .
请注意,下面的代码是基于您的其他问题(您已删除)。

import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ToggleButton;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.TilePane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.stage.Stage;

public class Nonogram extends Application {
    private static final int  COLS = 5;

    @Override
    public void start(Stage primaryStage) throws Exception {
        BorderPane root = new BorderPane();
        root.setCenter(createBoard());
        root.setLeft(createLeftPane());
        root.setTop(createTopPane());
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private TilePane createBoard() {
        TilePane board = new TilePane(Orientation.VERTICAL);
        board.setPrefRows(COLS);
        ObservableList<Node> children = board.getChildren();
        for (int row = 0; row < COLS; row++) {
            for (int col = 0; col < COLS; col++) {
                ToggleButton b = new ToggleButton();
                children.add(b);
            }
        }
        return board;
    }

    private Label createColumnLabel(String text) {
        Label label = new Label(text);
        label.setFont(Font.font("Monospaced"));
        label.setWrapText(true);
        label.setMinWidth(17);
        label.setPrefWidth(17);
        label.setMaxWidth(17);
        return label;
    }

    private VBox createLeftPane() {
        VBox leftPane = new VBox(createRowLabel("  3"),
                                 createRowLabel("  2"),
                                 createRowLabel("  2"),
                                 createRowLabel("  1"),
                                 createRowLabel("1 1"));
        return leftPane;
    }

    private Label createRowLabel(String text) {
        Label label = new Label(text);
        label.setFont(Font.font("Monospaced"));
        label.setMinHeight(25);
        label.setPrefHeight(25);
        label.setMaxHeight(25);
        return label;
    }

    private HBox createTopPane() {
        Rectangle rect = new Rectangle(22, 27);
        rect.setFill(Color.AZURE);
        HBox topPane = new HBox(rect,
                                createColumnLabel("1 1"),
                                createColumnLabel("  2"),
                                createColumnLabel("  4"),
                                createColumnLabel("  2"),
                                createColumnLabel("  3"));
        return topPane;
    }

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

可能有更好的方法来确定“提示”的大小和对齐方式,但我懒得去寻找。
下面是运行应用程序的屏幕截图。

pw136qt2

pw136qt22#

我认为最好的方法是使用2x2gridpane来保存行线索、列线索和拼图网格,左上部分留空。所有这三个部分将依次拥有自己的gridpane。所以在2x2屏幕的网格窗格中有3个网格窗格。
然后使用行和列约束来控制所有内容的对齐方式,并使拼图gridpane成为正方形。我已经把它划分成方法,这样数据加载的东西就可以和布局部分清楚地分开。

import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.scene.Scene;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
import javafx.scene.text.Text;
import javafx.stage.Stage;

import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Nonogram extends Application {
    private final GridPane puzzleGrid = new GridPane();
    private final GridPane columnClueGrid = new GridPane();
    private final GridPane rowClueGrid = new GridPane();

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

    @Override
    public void start(Stage primaryStage) {
        GridPane mainGrid = new GridPane();
        mainGrid.add(puzzleGrid, 1, 1);
        mainGrid.add(columnClueGrid, 1, 0);
        mainGrid.add(rowClueGrid, 0, 1);
        configureGrids();
        loadData();
        primaryStage.setScene(new Scene(mainGrid, 300, 270));
        primaryStage.show();
    }

    private void configureGrids() {
        columnClueGrid.getColumnConstraints()
                      .addAll(IntStream.range(0, 8).mapToObj(x -> createColumnConstraints(30)).collect(Collectors.toList()));
        rowClueGrid.getColumnConstraints()
                   .addAll(IntStream.range(0, 3).mapToObj(x -> createColumnConstraints(18)).collect(Collectors.toList()));
        rowClueGrid.getRowConstraints().addAll(IntStream.range(0, 8).mapToObj(x -> new RowConstraints(27)).collect(Collectors.toList()));
        puzzleGrid.getRowConstraints().addAll(IntStream.range(0, 8).mapToObj(x -> new RowConstraints(27)).collect(Collectors.toList()));
        puzzleGrid.getColumnConstraints()
                  .addAll(IntStream.range(0, 8).mapToObj(x -> createColumnConstraints(30)).collect(Collectors.toList()));
        puzzleGrid.gridLinesVisibleProperty().set(true);
    }

    private ColumnConstraints createColumnConstraints(double width) {
        ColumnConstraints results = new ColumnConstraints(width);
        results.setHalignment(HPos.CENTER);
        return results;
    }

    private void loadData() {
        String[][] rowClues =
                {{"1", "1", "1", "2", "", "2", "", ""}, {"1", "1", "1", "2", "1", "1", "", "6"}, {"3", "2", "2", "1", "1", "2", "7", "1"}};
        String[][] columnClues =
                {{"1", "1", "", "2", "", "", "", "1"}, {"2", "1", "1", "1", "1", "4", "3", "1"}, {"1", "3", "3", "2", "3", "2", "3", "3"}};
        for (int col = 0; col < 8; col++) {
            for (int row = 0; row < 3; row++) {
                columnClueGrid.add(new Text(columnClues[row][col]), col, row);
            }
        }
        for (int col = 0; col < 3; col++) {
            for (int row = 0; row < 8; row++) {
                rowClueGrid.add(new Text(rowClues[col][row]), col, row);
            }
        }
        for (int col = 0; col < 8; col++) {
            for (int row = 0; row < 8; row++) {
                puzzleGrid.add(new Text("X"), col, row);
            }
        }
    }
}

所以屏幕看起来是这样的:

在看到带有示例nonogram的注解后,我忍不住将其转换为一个完全工作的屏幕。因此,我用一个矩形替换了每个正方形中的“x”,单击可以在0和1之间切换不透明度:

import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;

import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Nonogram extends Application {
    private final GridPane puzzleGrid = new GridPane();
    private final GridPane columnClueGrid = new GridPane();
    private final GridPane rowClueGrid = new GridPane();

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

    @Override
    public void start(Stage primaryStage) {
        GridPane mainGrid = new GridPane();
        mainGrid.add(puzzleGrid, 1, 1);
        mainGrid.add(columnClueGrid, 1, 0);
        mainGrid.add(rowClueGrid, 0, 1);
        configureGrids();
        for (int col = 0; col < 8; col++) {
            for (int row = 0; row < 8; row++) {
                puzzleGrid.add(createRectangle(), col, row);
            }
        }
        loadData();
        primaryStage.setScene(new Scene(mainGrid, 300, 270));
        primaryStage.show();
    }

    private Node createRectangle() {
        Rectangle rectangle = new Rectangle(26, 23, Color.TEAL);
        rectangle.setOpacity(0);
        rectangle.setOnMouseClicked(evt -> {
            rectangle.setOpacity(1 - rectangle.getOpacity());
        });
        return rectangle;
    }

    private void configureGrids() {
        columnClueGrid.getColumnConstraints()
                      .addAll(IntStream.range(0, 8).mapToObj(x -> createColumnConstraints(30)).collect(Collectors.toList()));
        rowClueGrid.getColumnConstraints()
                   .addAll(IntStream.range(0, 3).mapToObj(x -> createColumnConstraints(18)).collect(Collectors.toList()));
        rowClueGrid.getRowConstraints().addAll(IntStream.range(0, 8).mapToObj(x -> new RowConstraints(27)).collect(Collectors.toList()));
        puzzleGrid.getRowConstraints().addAll(IntStream.range(0, 8).mapToObj(x -> new RowConstraints(27)).collect(Collectors.toList()));
        puzzleGrid.getColumnConstraints()
                  .addAll(IntStream.range(0, 8).mapToObj(x -> createColumnConstraints(30)).collect(Collectors.toList()));
        puzzleGrid.gridLinesVisibleProperty().set(true);
    }

    private ColumnConstraints createColumnConstraints(double width) {
        ColumnConstraints results = new ColumnConstraints(width);
        results.setHalignment(HPos.CENTER);
        return results;
    }

    private void loadData() {
        String[][] rowClues =
                {{"1", "1", "1", "2", "", "2", "", ""}, {"1", "1", "1", "2", "1", "1", "", "6"}, {"3", "2", "2", "1", "1", "2", "7", "1"}};
        String[][] columnClues =
                {{"1", "1", "", "2", "", "", "", "1"}, {"2", "1", "1", "1", "1", "4", "3", "1"}, {"1", "3", "3", "2", "3", "2", "3", "3"}};
        for (int col = 0; col < 8; col++) {
            for (int row = 0; row < 3; row++) {
                columnClueGrid.add(new Text(columnClues[row][col]), col, row);
            }
        }
        for (int col = 0; col < 3; col++) {
            for (int row = 0; row < 8; row++) {
                rowClueGrid.add(new Text(rowClues[col][row]), col, row);
            }
        }
    }
}

现在看起来是这样的:

fkvaft9z

fkvaft9z3#

看起来它正按照你的要求做。就像“西风”说的, GridPane 布局将节省你大量的手动定位。
你得换个姿势。他们看起来和我一模一样。但从长远来看,它仍然会给你带来麻烦。如果您最终想要更改窗口大小,布局管理器将为您处理这项工作。

相关问题