Получить частоту обновления монитора в JavaFX

Получение частоты обновления монитора с помощью AWT / Swing:

java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice() .getDisplayMode() .getRefreshRate()

Вопрос: Есть ли аналогичный метод / процедура для получения частоты обновления с помощью JavaFX? А если есть, как это сделать?

1 ответ

Нет эквивалентного общедоступного API в JavaFX

ЭтоDisplayMode.getRefreshRate()javadoc для API awt, который вы сейчас используете:

Возвращает частоту обновления дисплея в герцах.

Не существует эквивалентного общедоступного API JavaFX.

Если бы общедоступный API существовал в JavaFX, он, вероятно, был бы доступен через класс Screen , но там не определен метод доступа для такой функциональности.

Существует недокументированный, неподдерживаемый частный API, который, по-видимому, предлагает аналогичную функциональность:

      com.sun.javafx.tk.Toolkit.getToolkit().getRefreshRate()

Импульсная обработка JavaFX

Связанную информацию о том, как работает JavaFX, можно найти в документации по пульсу для описания архитектуры JavaFX.

Импульс — это событие, которое указывает графу сцены JavaFX, что пора синхронизировать состояние элементов графа сцены с Prism. Импульс ограничивается максимальной частотой 60 кадров в секунду (fps) и запускается всякий раз, когда на графе сцены выполняется анимация. Даже когда анимация не запущена, пульс запланирован, когда что-то в графике сцены изменяется. Например, при изменении положения кнопки планируется импульс.

При срабатывании импульса состояние элементов графа сцены синхронизируется вплоть до слоя рендеринга.

Аппаратная частота обновления экрана отличается от внутренней частоты обработки импульсов JavaFX. Хотя я предполагаю, что технически возможно, что они могут быть синхронизированы во внутренней реализации (и это может произойти в некоторых случаях), в общедоступной документации нет ничего, что упоминало бы, происходит ли это на самом деле.

Примечание о технологиях адаптивного обновления

Также обратите внимание, что с появлением таких технологий, как gsync и бесплатная синхронизация , частота обновления может быть адаптирована к содержимому.

Вертикальная синхронизация является опцией в большинстве систем, в которых видеокарта не может выполнять какие-либо действия, видимые для памяти дисплея, до тех пор, пока монитор не завершит текущий цикл обновления. . . такие технологии, как FreeSync и G-Sync, меняют концепцию и адаптируют частоту обновления дисплея к содержимому, поступающему с компьютера. Такие технологии требуют особой поддержки как со стороны видеоадаптера, так и со стороны дисплея.

Такие технологии делают идею полагаться на аппаратную частоту обновления монитора в лучшем случае немного размытой.

Ответы на часто задаваемые вопросы

Вы заявляете, что ваше намерение запрашивать частоту обновления дисплея:

Например, рисовать что-либо так же быстро, пока это все еще доступно для монитора...

JavaFX по умолчанию намеренно ограничен частотой кадров 60 кадров в секунду, независимо от характеристик монитора.

Это ограничение можно переопределить с помощью недокументированных системных свойств, как показано здесь:

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

Вот код, который имеет дело с исходным кодом openjfx .

      /*
 * Called to set the value of PULSE_DURATION or PULSE_DURATION_NS based on
 * the refresh rate of the primary screen (unless overridden by the
 * FRAMERATE_PROP Setting). If the refresh rate can not be determined the
 * default of 60hz is used.
 *
 * @param precision - precision in (1000 for ms or 1000000000 for ns)
 *
 * @return pulse duration value, either in ms or ns depending on the
 * parameter.
 */
protected int getPulseDuration(int precision) {
    int retVal = precision / 60;
    // Allow Setting to override monitor refresh
    if (Settings.get(FRAMERATE_PROP) != null) {
        int overrideHz = Settings.getInt(FRAMERATE_PROP, 60);
        if (overrideHz > 0) {
            retVal = precision / overrideHz;
        }
    } else if (Settings.get(PULSE_PROP) != null) {
        int overrideHz = Settings.getInt(PULSE_PROP, 60);
        if (overrideHz > 0) {
            retVal = precision / overrideHz;
        }
    } else {
        // If not explicitly set in Settings, try to set based on
        // refresh rate of display
        int rate = Toolkit.getToolkit().getRefreshRate();
        if (rate > 0) {
            retVal = precision / rate;
        }
        // if unknown, use default
    }
    return retVal;
}

В исходниках частота кадров регулируется недокументированным свойством, которое соответствует настройке в указанном выше источнике и что соответствует настройке .

Внутренний класс Toolkit предоставляет резервный API для использования частоты обновления дисплея.

Так что, возможно, вы могли бы добиться того, чего хотите, установив для системного свойства значение или установив оба а также обнулить. Я не пробовал это, поэтому я не знаю. Необходимо позаботиться о том, чтобы установленные вами значения корректно поддерживались и не переопределялись значениями по умолчанию.

Вы должны знать, что, если вы делаете это, вы используете недокументированные API-интерфейсы, поэтому для этого потребуется открыть соответствующие экспорты модулей, чтобы API-интерфейсы были доступны, а также могут быть удалены или стать несовместимыми без предварительного уведомления в будущих версиях платформы ( хотя эти настройки не менялись в течение многих лет).

Итак, я читал предоставленную вами ссылку, и мне кажется, что JavaFX просто застрял на скорости 60 кадров в секунду, потому что предпочитает?

По умолчанию да, это компромисс.

Для типов приложений, обычно разрабатываемых с использованием JavaFX, максимальное значение обновления 60 кадров в секунду в рамках механизма импульсного рендеринга обычно достаточно независимо от базовых аппаратных возможностей устройства. Повышение предела скорости выше этого уровня обычно не является хорошим компромиссом для большинства приложений JavaFX, поскольку это означает использование более высоких ресурсов (мощности ЦП и обработки видео и энергопотребления) для увеличения обновлений обновлений, которые обычно незаметны для большинства пользователей и часто не поддерживается базовым оборудованием.

Тем не менее, если вы хотите переопределить это ограничение по умолчанию, существуют недокументированные способы сделать это, как упоминалось выше.

Почему бы не использовать тот же метод?

Использование метода AWT может быть разумной альтернативой в этом случае.

Аппаратное обновление не изменится в зависимости от выбранного набора инструментов пользовательского интерфейса.

В настоящее время (JavaFX 17) система JavaFX зависит от упаковка ( модуль требует модуль, который содержит все классы awt). Итак, если JavaFX доступен, то учебный класс.

Поэтому, если цель состоит в том, чтобы определить частоту обновления оборудования, вы можете сделать это с помощью существующего API awt.

Частота обновления не изменится при использовании Swing или JavaFX, верно?

Аппаратная частота обновления не будет меняться в зависимости от используемого инструментария пользовательского интерфейса.

Определение частоты импульсов графа сцены в JavaFX для обновления рендеринга графа сцены в некоторой степени связано с частотой обновления, но является концепцией только для JavaFX, поскольку Swing не использует граф сцены на этапе рендеринга.

Другие вопросы по тегам