2014-06-06 32 views
2

所以,我想在javaFX中顯示一個棋盤。我將不得不執行不同的操作並繪製一些圖塊,因此我選擇使用每個圖塊的Canvas和GridPane以網格方式爲我排列它們。
不幸的是,我在調整網格圖塊的大小時遇到​​了一些問題;我想讓我的整個棋盤自動調整其大小以適應場景。因此,我已將ChangeListener添加到GridPane的高度和寬度屬性中,該屬性負責調整貼圖的大小。這隻適用於窗戶變大時,當窗戶縮小到一個更小的尺寸時,所有東西都變得更大!
這裏的最短SSCCE我想出了其再現了我的問題:與自動調整大小的棋盤

package chessboardtest; 

import javafx.application.Application; 
import javafx.beans.value.*; 
import javafx.geometry.*; 
import javafx.scene.*; 
import javafx.scene.canvas.*; 
import javafx.scene.control.*; 
import javafx.scene.layout.*; 
import javafx.scene.paint.*; 
import javafx.stage.Stage; 

public class ChessboardTest extends Application { 

    final int size = 10; 

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

     final GridPane chessboard = new GridPane(); 
     fillChessboard(chessboard, size); 

     ChangeListener<Number> resizeListener = new ChangeListener<Number>() { 

      @Override 
      public void changed(ObservableValue<? extends Number> ov, Number t, Number t1) { 
       double newWidth = chessboard.getWidth()/size; 
       double newHeight = chessboard.getHeight()/size; 

       for(Node n: chessboard.getChildren()) { 
        Canvas canvas = (Canvas)n; 
        canvas.setWidth(newWidth); 
        canvas.setHeight(newHeight); 
       } 
      } 
     }; 

     chessboard.widthProperty().addListener(resizeListener); 
     chessboard.heightProperty().addListener(resizeListener); 

     root.getChildren().add(chessboard); 
     root.setPadding(new Insets(10)); 
     VBox.setVgrow(chessboard, Priority.ALWAYS); 

     Scene scene = new Scene(root, 300, 250); 

     primaryStage.setTitle("chessboard"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    void fillChessboard(GridPane pane, int size) { 
     class RedrawListener implements ChangeListener<Number> { 
      Color color; 
      Canvas canvas; 
      public RedrawListener(Canvas c, int i) { 
       if(i % 2 == 0) { 
        color = Color.BLACK; 
       } 
       else { 
        color = Color.WHITE; 
       } 
       canvas = c; 
      } 

      @Override 
      public void changed(ObservableValue<? extends Number> ov, Number t, Number t1) { 
       canvas.getGraphicsContext2D().setFill(color); 
       canvas.getGraphicsContext2D().fillRect(0, 0, canvas.getWidth(), canvas.getHeight()); 
      } 
     } 

     for(int row = 0; row < size; row++) { 
      for(int col = 0, i = row; col < size; col++, i++) { 
       Canvas c = new Canvas(); 
       RedrawListener rl = new RedrawListener(c, i); 
       c.widthProperty().addListener(rl); 
       c.heightProperty().addListener(rl); 

       pane.add(c, row, col); 
      } 
     } 
    } 

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

''+1 SSCCE'' – Cruncher

+0

你真的需要一個帆布?你可以使用像'StackPane'這樣的方塊嗎? –

回答

5

如果你不需要一個畫布(你可能沒有),只要使用StackPane S爲正方形,並讓他們填寫寬度和高度。您可以隨時將畫布(或其他任何內容)添加到StackPane以顯示其內容。

import javafx.application.Application; 
import javafx.geometry.HPos; 
import javafx.geometry.VPos; 
import javafx.scene.Scene; 
import javafx.scene.control.Control; 
import javafx.scene.layout.ColumnConstraints; 
import javafx.scene.layout.GridPane; 
import javafx.scene.layout.Priority; 
import javafx.scene.layout.RowConstraints; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 

public class Chessboard extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     GridPane root = new GridPane(); 
     final int size = 8 ; 
     for (int row = 0; row < size; row++) { 
      for (int col = 0; col < size; col ++) { 
       StackPane square = new StackPane(); 
       String color ; 
       if ((row + col) % 2 == 0) { 
        color = "white"; 
       } else { 
        color = "black"; 
       } 
       square.setStyle("-fx-background-color: "+color+";"); 
       root.add(square, col, row); 
      } 
     } 
     for (int i = 0; i < size; i++) { 
      root.getColumnConstraints().add(new ColumnConstraints(5, Control.USE_COMPUTED_SIZE, Double.POSITIVE_INFINITY, Priority.ALWAYS, HPos.CENTER, true)); 
      root.getRowConstraints().add(new RowConstraints(5, Control.USE_COMPUTED_SIZE, Double.POSITIVE_INFINITY, Priority.ALWAYS, VPos.CENTER, true)); 
     } 
     primaryStage.setScene(new Scene(root, 400, 400)); 
     primaryStage.show(); 
    } 

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

這是一個不錯的解決方案,但在Java FX中使用數據綁定調整大小會容易得多。您可以用這種方式隱藏所有監聽器業務。 下面是正方形的解決方案就像詹姆斯·D的,但使用畫布的矩形insread:

public class ResizeChessboard extends Application { 
    GridPane root = new GridPane(); 
    final int size = 8; 

    public void start(Stage primaryStage) { 
     for (int row = 0; row < size; row++) { 
      for (int col = 0; col < size; col++) { 
       Rectangle square = new Rectangle(); 
       Color color; 
       if ((row + col) % 2 == 0) color = Color.WHITE; 
       else color = Color.BLACK; 
       square.setFill(color); 
       root.add(square, col, row); 
       square.widthProperty().bind(root.widthProperty().divide(size)); 
       square.heightProperty().bind(root.heightProperty().divide(size)); 
      } 
     } 
     primaryStage.setScene(new Scene(root, 400, 400)); 
     primaryStage.show(); 
    } 

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

謝謝,我也喜歡你的解決方案! – BlackBear