简体   繁体   中英

Dynamically resizing figures as the window is resized in JavaFX

I have an assignment where I am suppose to create 4 circles with 4 triangles inside to resemble a fan, create a clock that will randomly change its time each run of the program, and create a hangman figure. I have completed all of those figures but my final step is to make all the figures I created dynamically resize as the window is resized. I'm not sure how to accomplish this dynamic resizing but I believe it deals with binding which I don't really understand how to implement. If anyone can assist me that would be much appreciated. Here is my code below.

import javafx.application.*;
import javafx.stage.*;
import javafx.scene.*;
import javafx.geometry.*;
import javafx.scene.layout.*;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import java.util.*;
import javafx.scene.text.*;
import javafx.scene.control.*;
import java.lang.*;
import javafx.beans.binding.*;

public class test2 extends Application{

   @Override
   public void start(Stage primoStage){

      GridPane gridCircles = new GridPane();
      gridCircles.setPadding(new Insets(10));
      gridCircles.setHgap(5);
      gridCircles.setVgap(5);
      CirclePane cPane1 = new CirclePane();
      CirclePane cPane2 = new CirclePane();
      CirclePane cPane3 = new CirclePane();
      CirclePane cPane4 = new CirclePane();

      gridCircles.add(cPane1, 0, 0);
      gridCircles.add(cPane2, 1, 0);
      gridCircles.add(cPane3, 0, 1);
      gridCircles.add(cPane4, 1, 1);

      GridPane gridClock = new GridPane();
      gridClock.setPadding(new Insets(10));
      gridClock.setHgap(5);
      gridClock.setVgap(5);
      ClockPane clock = new ClockPane();
      String timeString = clock.getHour() + ":" + clock.getMinute() + ":" + clock.getSecond() + clock.getMeridiem();
      Label randomTime = new Label(timeString);
      gridClock.add(clock, 0, 0);
      GridPane.setHalignment(clock, HPos.CENTER);
      GridPane.setValignment(clock, VPos.CENTER);
      gridClock.add(randomTime, 0, 1);
      GridPane.setHalignment(randomTime, HPos.CENTER);
      GridPane.setValignment(randomTime, VPos.CENTER);

      GridPane gridHangMan = new GridPane();
      gridHangMan.setPadding(new Insets(10));
      gridHangMan.setHgap(5);
      gridHangMan.setVgap(5);
      hangingManPane hangMan = new hangingManPane();
      gridHangMan.add(hangMan, 0, 0);
      gridHangMan.setHalignment(hangMan, HPos.CENTER);
      gridHangMan.setValignment(hangMan, VPos.CENTER);

      GridPane gridPane = new GridPane();
      gridPane.setPadding(new Insets(10));
      gridPane.setHgap(5);
      gridPane.setVgap(5);
      gridPane.add(gridCircles, 0, 0);
      gridPane.add(gridClock, 1, 0);
      gridPane.add(gridHangMan, 2, 0);

      Scene scene = new Scene(gridPane, 1500, 500);
      primoStage.setTitle("Assignment 6 Test");
      primoStage.setScene(scene);
      primoStage.show();
   }

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

class CirclePane extends Pane {
  private Circle circle = new Circle(100,100,100);
  private Arc arc1 = new Arc(100,100,85,85,30,30);
  private Arc arc2 = new Arc(100,100,85,85,120,30);
  private Arc arc3 = new Arc(100,100,85,85,210,30);
  private Arc arc4 = new Arc(100,100,85,85,300,30);

   public CirclePane(){
      circle.setStroke(Color.BLACK);
      circle.setFill(Color.WHITE);
      arc1.setFill(Color.BLACK);
      arc1.setType(ArcType.ROUND);
      arc2.setFill(Color.BLACK);
      arc2.setType(ArcType.ROUND);
      arc3.setFill(Color.BLACK);
      arc3.setType(ArcType.ROUND);
      arc4.setFill(Color.BLACK);
      arc4.setType(ArcType.ROUND);
      getChildren().addAll(circle,arc1,arc2,arc3,arc4);
   }
}

class ClockPane extends Pane {
  private int hour;
  private int minute;
  private int second;
  private String meridiem;
  private double w = 400;
  private double h = 400;
  Random rand = new Random();

  public ClockPane(){
    setRandomTime();
  }

  public ClockPane(int hour, int minute, int second){
    this.hour = hour;
    this.minute = minute;
    this.second = second;
    paintClock();
  }

  public String getHour() {
    if (this.hour < 10){
      return "0"+hour;
    }
    return String.valueOf(hour);
  }

  public String getMinute() {
    if (this.minute <10){
      return "0"+minute;
    }
    return String.valueOf(minute);
  }

  public String getSecond() {
    if (this.second < 10){
      return "0"+second;
    }
    return String.valueOf(second);
  }

  public void setMinute(int minute) {
    this.minute = minute;
    paintClock();
  }

  public void setSecond(int second) {
    this.second = second;
  }

  public void setHour(int hour) {
    this.hour = hour;
  }

  public double getW() {
    return w;
  }

  public void setW(double w) {
    this.w = w;
    paintClock();
  }

  public double getH() {
    return h;
  }

  public void setH(double h) {
    this.h = h;
    paintClock();
  }

  public String getMeridiem() {
    if (Integer.valueOf(this.meridiem) > 12){
      return "pm";
    }
    return "am";
  }

  public void setMeridiem(String meridiem) {
    this.meridiem = meridiem;
  }

  public void setRandomTime() {
    Calendar calendar = new GregorianCalendar();

    this.hour = rand.nextInt(12 - 0 + 1) + 0;
    this.minute = rand.nextInt(60 - 0 + 1) + 0;
    this.second = rand.nextInt(60 - 0 + 1) + 0;
    this.meridiem = String.valueOf(rand.nextInt(24 - 0 +1) + 0);

    paintClock();
  }

  protected void paintClock() {
    double clockRadius = Math.min(w,h) * 0.8 * 0.5;
    double centerX = w/2;
    double centerY = h/2;

    Circle circle = new Circle(centerX, centerY, clockRadius);
    circle.setFill(Color.WHITE);
    circle.setStroke(Color.BLACK);
    Text t1 = new Text(centerX - 5, centerY - clockRadius + 14, "12");
    Text t2 = new Text(centerX - clockRadius + 3, centerY + 5, "9");
    Text t3 = new Text(centerX + clockRadius - 10, centerY + 3, "3");
    Text t4 = new Text(centerX - 3, centerY + clockRadius - 3, "6");

    double sLength = clockRadius * 0.8;
    double secondX = centerX + sLength * Math.sin(second * (2 * Math.PI / 60));
    double secondY = centerY - sLength * Math.cos(second * (2 * Math.PI / 60));
    Line sLine = new Line(centerX, centerY, secondX, secondY);
    sLine.setStroke(Color.RED);

    double mLength = clockRadius * 0.65;
    double xMinute = centerX + mLength * Math.sin(minute * (2 * Math.PI / 60));
    double minuteY = centerY - mLength * Math.cos(minute * (2 * Math.PI / 60));
    Line mLine = new Line(centerX, centerY, xMinute, minuteY);
    mLine.setStroke(Color.BLUE);

    double hLength = clockRadius * 0.5;
    double hourX = centerX + hLength * Math.sin((hour % 12 + minute / 60.0) * (2 * Math.PI / 12));
    double hourY = centerY - hLength * Math.cos((hour % 12 + minute / 60.0) * (2 * Math.PI / 12));
    Line hLine = new Line(centerX, centerY, hourX, hourY);
    hLine.setStroke(Color.GREEN);

    getChildren().clear();
    getChildren().addAll(circle, t1, t2, t3, t4, sLine, mLine, hLine);
  }
}

class hangingManPane extends Pane {
  private Arc arc1 = new Arc(100, 450, 100, 100, 45, 90);
  private Line line1 = new Line(100, 50, 100 ,350);
  private Line line2 = new Line(100, 50, 300, 50);
  private Line line3 = new Line(300, 50, 300, 100);
  private Circle circle = new Circle(300, 130, 30);
  private Line line4 = new Line(285, 160, 225, 250);
  private Line line5 = new Line(315, 160, 375, 250);
  private Line line6 = new Line(300, 160, 300, 280);
  private Line line7 = new Line(300, 280, 250, 360);
  private Line line8 = new Line(300, 280, 350, 360);

  public hangingManPane() {
    arc1.setFill(Color.TRANSPARENT);
    arc1.setType(ArcType.OPEN);
    arc1.setStroke(Color.BLACK);
    arc1.setStrokeWidth(5);
    line1.setStroke(Color.BLACK);
    line1.setStrokeWidth(5);
    line2.setStroke(Color.BLACK);
    line2.setStrokeWidth(5);
    line3.setStroke(Color.BLACK);
    line3.setStrokeWidth(5);
    circle.setStroke(Color.BLACK);
    circle.setFill(Color.TRANSPARENT);
    circle.setStrokeWidth(5);
    line4.setStroke(Color.BLACK);
    line4.setStrokeWidth(5);
    line5.setStroke(Color.BLACK);
    line5.setStrokeWidth(5);
    line6.setStroke(Color.BLACK);
    line6.setStrokeWidth(5);
    line7.setStroke(Color.BLACK);
    line7.setStrokeWidth(5);
    line8.setStroke(Color.BLACK);
    line8.setStrokeWidth(5);
    getChildren().addAll(arc1, line1, line2, line3, circle, line4, line5, line6, line7, line8);
  }
}

You could simply scale the gridPane to the appropriate size. Since you'll probably want to preserve the initial aspect ratio, you could wrap it in a StackPane to align the content properly after scaling:

// keep gridPane at original size
gridPane.setMinSize(1500, 500);
gridPane.setMaxSize(1500, 500);

StackPane root = new StackPane(gridPane);
// root.setAlignment(Pos.TOP_LEFT);

// use gridPane size to determine the factor to scale by
NumberBinding maxScale = Bindings.min(root.widthProperty().divide(1500),
                                      root.heightProperty().divide(500));
gridPane.scaleXProperty().bind(maxScale);
gridPane.scaleYProperty().bind(maxScale);

Scene scene = new Scene(root, 1500, 500);

You have to just replace your following code..

GridPane gridPane = new GridPane();
      gridPane.setPadding(new Insets(10));
      gridPane.setHgap(5);
      gridPane.setVgap(5);
      gridPane.add(gridCircles, 0, 0);
      gridPane.add(gridClock, 1, 0);
      gridPane.add(gridHangMan, 2, 0);

      Scene scene = new Scene(gridPane, 1500, 500);
      primoStage.setTitle("Assignment 6 Test");
      primoStage.setScene(scene);
      primoStage.show();

with

ScalableContentPane scale = new ScalableContentPane();
    GridPane gridPane = new GridPane();
    gridPane.setPadding(new Insets(10));
    gridPane.setHgap(5);
    gridPane.setVgap(5);
    gridPane.add(gridCircles, 0, 0);
    gridPane.add(gridClock, 1, 0);
    gridPane.add(gridHangMan, 2, 0);
    scale.setContent(gridPane);
    Scene scene = new Scene(scale, 1650, 500);
    primoStage.setTitle("Assignment 6 Test");
    primoStage.setScene(scene);
    primoStage.show();

Using fololowing library.. https://mvnrepository.com/artifact/eu.mihosoft.jfx.scaledfx/scaledfx/0.3

I have something similar, a webview that when I resize the window it resizes too

    WebView advertising = new WebView();
    WebEngine webEngine = advertising.getEngine();
    webEngine.load(urlAdvertising);

    advertising.minHeightProperty().bind(view.widthProperty());
    advertising.minWidthProperty().bind(view.widthProperty());

Hope it works for you! (;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM