Css 数独图形用户界面网格线

Css 数独图形用户界面网格线,css,javafx,Css,Javafx,堆栈溢出第一个计时器在这里 首先,我正在使用JavaFX创建一个数独解算器。我已经做了所有的工作,但是,我唯一的问题是创建粗体的3x3大块,每个大块内有3x3个单元格。我尝试为大的块创建2个“for”循环,然后为每个小的TextField单元格再创建2个“for”循环。然而,从那时起,访问这些细胞似乎是不可能的,从技术上讲,我将创建一个4-d阵列,我必须以某种方式访问这些混乱 因此,我放弃了美学,使用9x9 TextField单元格,但没有适当的数独行。它与解算器一起工作,但现在我想添加这些行,

堆栈溢出第一个计时器在这里

首先,我正在使用JavaFX创建一个数独解算器。我已经做了所有的工作,但是,我唯一的问题是创建粗体的3x3大块,每个大块内有3x3个单元格。我尝试为大的块创建2个“for”循环,然后为每个小的TextField单元格再创建2个“for”循环。然而,从那时起,访问这些细胞似乎是不可能的,从技术上讲,我将创建一个4-d阵列,我必须以某种方式访问这些混乱

因此,我放弃了美学,使用9x9 TextField单元格,但没有适当的数独行。它与解算器一起工作,但现在我想添加这些行,因为我可能会让它看起来像一个合法的数独网格。考虑过使用CSS,但第n个孩子不使用JavaFXCSS。谢谢你,亚尔

    public class SudokuGUI extends Application {

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

public static LimitedNumberTextField[][] tf2D = 
        new LimitedNumberTextField[9][9];
public static int[][] tf2DVal = new int[9][9];
public static int[][] output = SudokuSolver.output;
public static int[][] zeroBoard = SudokuSolver.zeroSudoku;

@Override
public void start(Stage mainStage) throws Exception {

    //Solve Button
    Button solveButton = new Button("Solve");
    solveButton.setMaxWidth(Double.MAX_VALUE);
    solveButton.setStyle("-fx-background-color: "
            + "linear-gradient(#f2f2f2, #d6d6d6), "
            + "linear-gradient(#fcfcfc 0%, #d9d9d9 20%, #d6d6d6 100%),"
            + "linear-gradient(#dddddd 0%, #f6f6f6 50%);"
            + "-fx-background-radius: 8,7,6;"
            + "-fx-background-insets: 0,1,2;" 
            + "-fx-text-fill: black;"
            + "-fx-effect: dropshadow( three-pass-box , "
            + "rgba(0,0,0,0.6) , 5, 0.0 , 0 , 1 );");

    //Reset Button
    Button resetButton = new Button("Reset");
    resetButton.setMaxWidth(Double.MAX_VALUE);
    resetButton.setStyle("-fx-background-color: "
            + "linear-gradient(#f2f2f2, #d6d6d6), "
            + "linear-gradient(#fcfcfc 0%, #d9d9d9 20%, #d6d6d6 100%),"
            + "linear-gradient(#dddddd 0%, #f6f6f6 50%);"
            + "-fx-background-radius: 8,7,6;"
            + "-fx-background-insets: 0,1,2;" 
            + "-fx-text-fill: black;"
            + "-fx-effect: dropshadow( three-pass-box , "
            + "rgba(0,0,0,0.6) , 5, 0.0 , 0 , 1 );");

    //Grid
    GridPane grid = new GridPane();
    grid.setPadding(new Insets(40, 40, 40, 40));

    //Setting the grid to the scene.
    Scene scene = new Scene(grid);

    // Will hold the 2 buttons in a vBox.
    VBox vb = new VBox();
    vb.setPadding(new Insets(10, 0, 0, 30));
    vb.setSpacing(10);
    vb.getChildren().addAll(solveButton, resetButton);

    GridPane.setRowIndex(vb, 0);
    GridPane.setColumnIndex(vb, 4);

    // Adds in the vBox consisting of the 2 buttons onto the GridPane.
    grid.getChildren().add(vb);

    grid.setStyle("-fx-background-color: linear-gradient(to bottom, "
            + "#cedbe9 0%,#aac5de 17%,#6199c7 50%,#3a84c3 51%,"
            + "#419ad6 59%,#4bb8f0 71%,#3a8bc2 84%,#26558b 100%);");

    // Creation of Sudoku grid consisting of 81 total cells.
    GridPane box = new GridPane();
        box.setStyle("-fx-background-color: black, "
                + "-fx-control-inner-background; "
                + "-fx-background-insets: 0, 2; " 
                + "-fx-padding: 4;"
                + "-fx-grid-lines-visible: true;");
        for (int row = 0; row < 9; row++) {
            for (int col = 0; col < 9; col++) {
                LimitedNumberTextField limitNumberTextField = 
                        new LimitedNumberTextField(1);
                limitNumberTextField.setStyle(
                        "-fx-pref-width: 3em; " 
                        + "-fx-pref-height: 3em;");
                GridPane.setConstraints(limitNumberTextField, row, col);
                box.getChildren().add(limitNumberTextField);

                if (limitNumberTextField.getText().equals("")) {
                    limitNumberTextField.setText("0");
                }
                tf2D[row][col]= limitNumberTextField;

                tf2DVal[row][col] = Integer
                        .parseInt(limitNumberTextField.getText());

                if (limitNumberTextField.getText().equals("0")) {
                    limitNumberTextField.setText("");
                    tf2D[row][col] = limitNumberTextField;
                }
            }
        }

    grid.getChildren().add(box);

    //Action Listeners for the buttons.
    try {
        solveButton.setOnAction(e -> {
            getBoard();
            setBoard(tf2DVal);

            if (isZeroBoard(tf2DVal)) {
                Alert alert = new Alert(AlertType.INFORMATION);
                alert.setTitle(" No values!! ");
                alert.setHeaderText(null);
                alert.setContentText(
                        " Please input some values and try again.");
                alert.showAndWait();
                return;
            }
            try {
                SudokuSolver.solveIt(tf2DVal);
            } catch (Exception e1) {
                Alert alert = new Alert(AlertType.INFORMATION);
                alert.setTitle(" Invalid Sudoku board! ");
                alert.setHeaderText(null);
                alert.setContentText(" Your input is invalid! \n"
                        + " Please check your board and try again.");
                alert.showAndWait();
            }
            setFinalBoard();
        });

        resetButton.setOnAction(e -> {
            getBoard();
            resetBoard();
        });

        //Shows hand when hovered over. 
        solveButton.setOnMouseEntered(e -> {
            solveButton.setCursor(Cursor.HAND);
        });

        resetButton.setOnMouseEntered(e -> {
            resetButton.setCursor(Cursor.HAND);
        });

    } catch (Exception e) { // In case there is no solution. Not likely. 
        Alert alert = new Alert(AlertType.INFORMATION);
        alert.setTitle(" No Solution Found! ");
        alert.setHeaderText(null);
        alert.setContentText(
                "Please check your board and try again. ");
        alert.showAndWait();
    }
    mainStage.setTitle("Sudoku Solver");
    mainStage.getIcons().add(new Image("file:logo_icon.png"));
    mainStage.setScene(scene);
    mainStage.show();
}

//Reading the values of the Sudoku. 
public static void getBoard() {
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            LimitedNumberTextField ltf = tf2D[i][j];
            if (ltf.getText().equals("")) {
                ltf.setText("0");
            }

            tf2DVal[i][j] = 0;
            tf2DVal[i][j] = Integer.parseInt(ltf.getText());

            if (ltf.getText().equals("0")) {
                ltf.setText("");
                tf2D[i][j] = ltf;
            }

        }
    }
}

//Setting the values to the board. 
public static void setBoard(int[][] board) {
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            tf2DVal[i][j] = board[i][j];

            if (tf2D[i][j].getText().equals("")) {
                tf2D[i][j].setText("0");
            }

            tf2D[i][j].setText(Integer.toString(tf2DVal[i][j]));

            if (tf2D[i][j].getText().equals("0")) {
                tf2D[i][j].setText("");
            }
        }
    }
}

//Method to set the final value after it is solved. 
public static void setFinalBoard() {
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            tf2DVal[i][j] = output[i][j];
            if (tf2D[i][j].getText().equals("")) {
                tf2D[i][j].setText("0");
            }
            tf2D[i][j].setText(Integer.toString(tf2DVal[i][j]));
            if (tf2D[i][j].getText().equals("0")) {
                tf2D[i][j].setText("");
            }
        }
    }
}

//Resets the board.
public static void resetBoard() {
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            tf2D[i][j].setText("");
        }
    }
}

//This method compares the board to a board with all zeros. 
public static boolean isZeroBoard(int[][] input) {
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            if (!(input[i][j] == zeroBoard[i][j])) {
                return false;
            }
        }
    }
    return true;
}

}我的基本想法是将文本字段放在另一个容器中,例如堆栈窗格,然后向堆栈窗格添加一些样式。您应该使用外部样式表来定义样式

由于样式取决于块内单元的位置,因此需要根据该位置以某种方式操纵样式类。实际上,第2行和第5行的底部需要一个边框,第2列和第5列的右侧需要一个边框。我认为最干净的方法是设置或取消设置CSS,以指示单元格是否位于相应块的右列或底行

要生成实际边界,请使用嵌套背景方法。基本思想是绘制两个矩形背景。第一个用于边界,并填充整个空间。第二个用于边框内的部分,并绘制在第一个的顶部,但沿希望边框可见的边缘插入一个1像素

CSS看起来像:

sudoku.css:

.root {
    -fx-padding: 5px ;
}

.cell {

    /* Defines a black border around the standard color -fx-base */
    -fx-background-color:  black, -fx-base ;

    /* By default draw the base color over the whole region, so no border visible */
    -fx-background-insets: 0, 0 ;

    -fx-padding: 5px ;
}

.cell:right {
    -fx-background-insets: 0, 0 1 0 0 ;
}

.cell:bottom {
    -fx-background-insets: 0, 0 0 1 0 ;
}

.cell:right:bottom {
    -fx-background-insets: 0, 0 1 1 0 ;
}

.cell .text-field {
    -fx-pref-width: 3em ;
    -fx-pref-height: 3em ;
}
下面是一个使用它的示例:

import javafx.application.Application;
import javafx.css.PseudoClass;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class SudokuBoard extends Application {

    @Override
    public void start(Stage primaryStage) {

        GridPane board = new GridPane();

        PseudoClass right = PseudoClass.getPseudoClass("right");
        PseudoClass bottom = PseudoClass.getPseudoClass("bottom");

        for (int col = 0; col < 9; col++) {
            for (int row = 0; row < 9; row++) {
                StackPane cell = new StackPane();
                cell.getStyleClass().add("cell");
                cell.pseudoClassStateChanged(right, col == 2 || col == 5);
                cell.pseudoClassStateChanged(bottom, row == 2 || row == 5);

                cell.getChildren().add(createTextField());

                board.add(cell, col, row);
            }
        }


        Scene scene = new Scene(board);
        scene.getStylesheets().add("sudoku.css");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private TextField createTextField() {
        TextField textField = new TextField();

        // restrict input to integers:
        textField.setTextFormatter(new TextFormatter<Integer>(c -> {
            if (c.getControlNewText().matches("\\d?")) {
                return c ;
            } else {
                return null ;
            }
        }));
        return textField ;
    }

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

我将使用的基本思想是将文本字段放在另一个容器(例如StackPane)中,然后向stack pane添加一些样式。您应该使用外部样式表来定义样式

由于样式取决于块内单元的位置,因此需要根据该位置以某种方式操纵样式类。实际上,第2行和第5行的底部需要一个边框,第2列和第5列的右侧需要一个边框。我认为最干净的方法是设置或取消设置CSS,以指示单元格是否位于相应块的右列或底行

要生成实际边界,请使用嵌套背景方法。基本思想是绘制两个矩形背景。第一个用于边界,并填充整个空间。第二个用于边框内的部分,并绘制在第一个的顶部,但沿希望边框可见的边缘插入一个1像素

CSS看起来像:

sudoku.css:

.root {
    -fx-padding: 5px ;
}

.cell {

    /* Defines a black border around the standard color -fx-base */
    -fx-background-color:  black, -fx-base ;

    /* By default draw the base color over the whole region, so no border visible */
    -fx-background-insets: 0, 0 ;

    -fx-padding: 5px ;
}

.cell:right {
    -fx-background-insets: 0, 0 1 0 0 ;
}

.cell:bottom {
    -fx-background-insets: 0, 0 0 1 0 ;
}

.cell:right:bottom {
    -fx-background-insets: 0, 0 1 1 0 ;
}

.cell .text-field {
    -fx-pref-width: 3em ;
    -fx-pref-height: 3em ;
}
下面是一个使用它的示例:

import javafx.application.Application;
import javafx.css.PseudoClass;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class SudokuBoard extends Application {

    @Override
    public void start(Stage primaryStage) {

        GridPane board = new GridPane();

        PseudoClass right = PseudoClass.getPseudoClass("right");
        PseudoClass bottom = PseudoClass.getPseudoClass("bottom");

        for (int col = 0; col < 9; col++) {
            for (int row = 0; row < 9; row++) {
                StackPane cell = new StackPane();
                cell.getStyleClass().add("cell");
                cell.pseudoClassStateChanged(right, col == 2 || col == 5);
                cell.pseudoClassStateChanged(bottom, row == 2 || row == 5);

                cell.getChildren().add(createTextField());

                board.add(cell, col, row);
            }
        }


        Scene scene = new Scene(board);
        scene.getStylesheets().add("sudoku.css");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private TextField createTextField() {
        TextField textField = new TextField();

        // restrict input to integers:
        textField.setTextFormatter(new TextFormatter<Integer>(c -> {
            if (c.getControlNewText().matches("\\d?")) {
                return c ;
            } else {
                return null ;
            }
        }));
        return textField ;
    }

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

那是不可编译的。请创建一个矩形。为什么不尝试使用9 x 9矩形?我有一个答案:脱离主题的建议,但是,使用外部CSS文件,而不是嵌入在代码中的样式属性。您可能还希望在SceneBuilder中设计至少部分UI,并将FXML用于布局而不是代码。在这里可以找到一个很好的答案,这也是一个不可编译的工作示例。请创建一个矩形。为什么不尝试使用9 x 9矩形?我有一个答案:脱离主题的建议,但是,使用外部CSS文件,而不是嵌入在代码中的样式属性。您可能还希望在SceneBuilder中设计至少部分UI,并将FXML用于布局而不是代码