85933

Chessboard with automatic resizing

So, I am trying to display a chessboard in javaFX. I will have to perform different operations and draw on some of the tiles so I chose to use a Canvas for each tile and a GridPane to arrange them for me in a grid fashion. Unfortunately I am having some problems with the resizing of the grid tiles; I want my whole chessboard to automatically adapt its size to the Scene. Therefore, I have added a ChangeListener to both the height and width properties of the GridPane which takes care of resizing the tiles. This only works when the window gets bigger, when the window is reduced to a smaller size everything still gets bigger! Here's the shortest SSCCE I came up with which reproduces my problem:

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); } }

Answer1:

If you don't need a canvas (and you probably don't), just use StackPanes for the squares and make them fill the width and the height. You can always add a canvas (or anything else) to the StackPanes to display their content.

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); } }

Answer2:

This is a nice solution, but resizing is so much easier with data binding in Java FX. You can hide all listener business this way. Here is a solution much like James D's, but using Rectangles insread of Canvases for the squares:

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); } }

Recommend

  • Error Deploying to Heroku Play 2.2 app
  • How i change fill color of graphics in create js
  • Visual Studio 2017 compatibality with boost 1.64.0/1.63.0 issue
  • What are some techniques to monitor multiple instances of a piece of software?
  • How to reduce the time delay to reach run method of Runnable class using ExecutorService Java
  • IBM DevOps Pipeline: How to Access Artifacts from Previous Job?
  • Circle movement upon rectangle Collision
  • Differences between drawing an Ellipse in Android and Java
  • Exception in the iconization of JInternalFrame with DefaultDesktopManager
  • write text on image and show it to a imageview
  • I have two activity.I want to Send the data from second activity to previous activity.First activity
  • Custom WebViewPage inject code when razor template is rendering
  • Unable to resolve Static method?
  • Parenthesis() and SQL Query Performance
  • How to display a tooltip according to mouse position? - JavaFX
  • Activity overlaying. WindowManager.LayoutParams
  • How to get listview position?
  • Syntax error on tokens, AnnotationName expected instead - error on query
  • WPF version of .ScaleControl?
  • Linq Merge lists
  • Android Activity.onWindowFocusChanged doesn't get called from within TabHost
  • presentShareDialogWithParams posts to FB wall, but callback handler results say error
  • how to adjust image in a panel in Java swing?
  • how to do an event when i swipe from fragment to the other
  • Possible to stop flickering java tooltip in heavyweight mode?
  • align graphs with different xlab
  • Akka Routing: Reply's send to router ends up as dead letters
  • Cannot Parse HTML Data Using Android / JSOUP
  • How get height of the a view with gone visibility and height defined as wrap_content in xml?
  • JTable with a ScrollPane misbehaving
  • FormattedException instead of throw new Exception(string.Format(…)) in .NET
  • Java static initializers and reflection
  • unknown Exception android
  • Sorting a 2D array using the second column C++
  • Observable and ngFor in Angular 2
  • failed to connect to specific WiFi in android programmatically
  • Unable to use reactive element in my shiny app
  • java string with new operator and a literal
  • How can I use threading to 'tick' a timer to be accessed by other threads?
  • jQuery Masonry / Isotope and fluid images: Momentary overlap on window resize