Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8191470

JavaFX Stage bounds get updated before and after maximized property is changed

XMLWordPrintable

      FULL PRODUCT VERSION :
      java version "9.0.1"
      Java(TM) SE Runtime Environment (build 9.0.1+11)
      Java HotSpot(TM) 64-Bit Server VM (build 9.0.1+11, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601], Ubuntu 14.04 (Unity), Ubuntu 16.04 (Unity, Gnome 3), ...

      EXTRA RELEVANT SYSTEM CONFIGURATION :
      Nothing unusual

      A DESCRIPTION OF THE PROBLEM :
      If a JavaFX Stage is maximized by the user, then first the x and y properties of the stage are changed, then the maximized property is set to true and after that the width and height properties are changed.

      This order of events makes it impossible to remember the original bounds of the stage right before maximization.

      Example output of order for maximizing the stage:

      1: max=false Rectangle2D [minX = 552.0, minY=261.0, maxX=1368.0, maxY=899.0, width=816.0, height=638.0]
      2: max=false Rectangle2D [minX = -8.0, minY=261.0, maxX=808.0, maxY=899.0, width=816.0, height=638.0]
      3: max=false Rectangle2D [minX = -8.0, minY=-8.0, maxX=808.0, maxY=630.0, width=816.0, height=638.0]
      4: max=true Rectangle2D [minX = -8.0, minY=-8.0, maxX=808.0, maxY=630.0, width=816.0, height=638.0]
      5: max=true Rectangle2D [minX = -8.0, minY=-8.0, maxX=1928.0, maxY=630.0, width=1936.0, height=638.0]
      6: max=true Rectangle2D [minX = -8.0, minY=-8.0, maxX=1928.0, maxY=1168.0, width=1936.0, height=1176.0]

      Step 1: Shows the initial bounds of the stage before maximization.
      Step 2-3: The x and y properties get changed.
      Step 4: The maximized property is set.
      Step 5-6: The width and height properties get changed.

      Example output of order for restoring the stage:

      1: max=true Rectangle2D [minX = -8.0, minY=-8.0, maxX=1928.0, maxY=1168.0, width=1936.0, height=1176.0]
      2: max=true Rectangle2D [minX = 552.0, minY=-8.0, maxX=2488.0, maxY=1168.0, width=1936.0, height=1176.0]
      3: max=true Rectangle2D [minX = 552.0, minY=261.0, maxX=2488.0, maxY=1437.0, width=1936.0, height=1176.0]
      4: max=false Rectangle2D [minX = 552.0, minY=261.0, maxX=2488.0, maxY=1437.0, width=1936.0, height=1176.0]
      5: max=false Rectangle2D [minX = 552.0, minY=261.0, maxX=1368.0, maxY=1437.0, width=816.0, height=1176.0]
      6: max=false Rectangle2D [minX = 552.0, minY=261.0, maxX=1368.0, maxY=899.0, width=816.0, height=638.0]

      Step 1: Shows the initial bounds in maximized state.
      Step 2-3: The x and y properties get restored.
      Step 4: The maximized property is unset.
      Step 5-6: The width and height properties get restored.

      This order of events is terrible, because it state of the maximized property changes midway during the transition. The maximized property should be changed first while maximizing the stage (order: 4,1,2,3,5,6) and changed last while restoring the initial bounds (order: 1,2,3,5,6,4).

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Add a single InvalidationListener to the properties x, y, width, height, maximized of a Stage instance and print out the values of these properties on every change.

      Stage stage = new Stage();
      InvalidationListener listener = (ob) -> {
          System.out.println("max=" + stage.isMaximized() + ", x=" + stage.getX() + ", y=" + stage.getY() + ", width=" + stage.getWidth() + ", height=" + stage.getHeight());
      };

      stage.xProperty().addListener(listener);
      stage.yProperty().addListener(listener);
      stage.widthProperty().addListener(listener);
      stage.heightProperty().addListener(listener);
      stage.maximizedProperty().addListener(listener);

      stage.show();

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      A described above, the maximized property should change first when the Stage gets maximized and should change last if the Stage gets restored.
      ACTUAL -
      The bounds (x,y, width, height) of the stage returned at the time the maximized property changes are invalid, because they only represent only a half state of the actual change.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package de.asysgmbh.immo;

      import javafx.application.Application;
      import javafx.beans.InvalidationListener;
      import javafx.scene.Scene;
      import javafx.scene.layout.VBox;
      import javafx.stage.Stage;

      public class StageEventTest extends Application {

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

      VBox root = new VBox();
      Scene scene = new Scene(root);
      ps.setScene(scene);

      InvalidationListener listener = (o) -> {
      System.out.printf(
      "max=%b, x=%d, y=%d, w=%d, h=%d\r\n",
      ps.isMaximized(),
      (int) ps.getX(),
      (int) ps.getY(),
      (int) ps.getWidth(),
      (int) ps.getHeight());
      };

      ps.maximizedProperty().addListener(listener);
      ps.xProperty().addListener(listener);
      ps.yProperty().addListener(listener);
      ps.widthProperty().addListener(listener);
      ps.heightProperty().addListener(listener);

      ps.show();
      }

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

      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      There is none to be found.

            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: