Размер сцены JavaFX непредсказуем после шоу () - PullRequest
0 голосов
/ 02 июля 2018

ОС: RHEL 7.4
DE: KDE Plasma 4.11.19 и GNOME 3.22.2
Версия Java: 9 и 10

У меня возникают проблемы при попытке определить размер рабочей области после вызова show (). Раньше в Java 8 / RHEL 6 все работало нормально, и я смог получить размер рабочей области последовательно после show (). Я бы просто послушал свойство width и height, но похоже, что есть обновление для самой сцены, а затем еще одно обновление, добавляющее размер декорации, но что если размер декорации равен 0, как в этом примере ширина декорации равно 0, поэтому я не могу просто слушать два изменения, каждое из которых имеет свойство width и height.

Я делаю это неправильно? Могу ли я послушать какое-нибудь другое событие, которое гарантирует, что сцена будет полностью инициализирована после show ()? Я добавил пример кода, демонстрирующий проблему ниже.

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.stage.Stage;

public class JavaFXTest extends Application {

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

  @Override
  public void start(final Stage primaryStage) throws Exception {
    primaryStage.widthProperty().addListener(new ChangeListener<Number>() {
      @Override
      public void changed(final ObservableValue<? extends Number> observable, final Number oldValue, final Number newValue) {
       System.out.println("Width changed! Previous value = " + oldValue + ", new value = " + newValue);
      }
    });
    primaryStage.heightProperty().addListener(new ChangeListener<Number>() {
      @Override
      public void changed(final ObservableValue<? extends Number> observable, final Number oldValue, final Number newValue) {
       System.out.println("Height changed! Previous value = " + oldValue + ", new value = " + newValue);
      }
    });
    primaryStage.showingProperty().addListener(new ChangeListener<Boolean>() {
      @Override
      public void changed(final ObservableValue<? extends Boolean> observable, final Boolean oldValue, final Boolean newValue) {
        if(newValue) {
          Platform.runLater(() -> {
            final double width = primaryStage.getWidth();
            final double height = primaryStage.getHeight();
            System.out.println("Stage width and height after change to showing property (Platform.runLater): " + width + ", " + height);
          });
        }
      }
    });
    primaryStage.showingProperty().addListener(new ChangeListener<Boolean>() {
      @Override
      public void changed(final ObservableValue<? extends Boolean> observable, final Boolean oldValue, final Boolean newValue) {
        if(newValue) {
          final double width = primaryStage.getWidth();
          final double height = primaryStage.getHeight();
          System.out.println("Stage width and height after change to showing property: " + width + ", " + height);
        }
      }
    });
    primaryStage.show();
    Platform.runLater(() -> {
      final double width = primaryStage.getWidth();
      final double height = primaryStage.getHeight();
      System.out.println("Stage width and height immediately after show (Platform.runLater): " + width + ", " + height);
    });
    final double width = primaryStage.getWidth();
    final double height = primaryStage.getHeight();
    System.out.println("Stage width and height immediately after show:" + width + ", " + height);
  }
}

Вот некоторые возможные результаты этой программы. Вывод противоречивый.

Вывод в GNOME (и KDE, номера отличаются)
Пример дела 1:
Ширина и высота этапа после изменения для показа свойства: NaN, NaN
Ширина и высота сцены сразу после шоу: NaN, NaN
Ширина и высота рабочей области после изменения отображаемого свойства (Platform.runLater): NaN, NaN
Ширина и высота сцены сразу после шоу (Platform.runLater): NaN, NaN
Ширина изменилась! Предыдущее значение = NaN, новое значение = 318,0
Высота изменилась! Предыдущее значение = NaN, новое значение = 171,0
Высота изменилась! Предыдущее значение = 171,0, новое значение = 208,0

Пример, пример 2:
Ширина и высота этапа после изменения показанного свойства: NaN, NaN
Ширина и высота сцены сразу после шоу: NaN, NaN
Ширина изменилась! Предыдущее значение = NaN, новое значение = 318,0
Высота изменилась! Предыдущее значение = NaN, новое значение = 171,0
Ширина и высота рабочей области после изменения отображаемого свойства (Platform.runLater): 318,0, 171,0
Ширина и высота сцены сразу после шоу (Platform.runLater): 318,0, 171,0
Высота изменилась! Предыдущее значение = 171,0, новое значение = 208,0

РЕДАКТИРОВАТЬ: Похоже, что 2-й проход, чтобы добавить в декорации не гарантируется и будет выполняться на 1-м проходе время от времени.

Ответы [ 2 ]

0 голосов
/ 24 июля 2018

Заканчивается с этим ответом . Немного изменил его, чтобы подождать как минимум 2 события (начальную ширину и высоту), прежде чем ждать, чтобы увидеть, есть ли еще какие-то после некоторого периода времени.

Я не совсем доволен этим решением, но оно пока работает и все еще чувствует себя быстро. Вне привязки к нативным библиотекам я не уверен, что еще я могу сделать.

Проблемы, вызванные этим решением, - это отображение в неправильном месте перед перемещением туда, куда я хочу. Попытка использовать setOpacity (0) перед show () и затем setOpacity (1) после инициализации, кажется, только несколько смягчает проблему, поскольку иногда она все еще отображается в неправильном положении в течение доли секунды.

0 голосов
/ 13 июля 2018

Я не могу дать однозначный ответ, так как я не очень разбираюсь в JavaFX.

Все ли окна украшены? Если нет, вы можете сначала выполнить проверку StageStyle и ответить только после завершения украшения.

Если все окна оформлены, ждет ли изменения, чтобы применить параметр? Если ожидание не является вариантом, обновляются ли свойства outputScaleX и ouputScaleY после применения возможного оформления? Если нет, используйте их вместо этого.

И, наконец, сам Stage не содержит свойств width и height, это свойства расширяемого Window. Вы всегда можете попробовать использовать свойства renderScaleX и renderScaleY и взять любое место для рамки / полей / и т. Д. учитывается при работе с этими значениями.

В противном случае вы можете ответить на оба события в качестве окончательного решения.

...