JavaFX全屏-根据屏幕大小调整元素的大小 [英] JavaFX fullscreen - resizing elements based upon screen size

查看:207
本文介绍了JavaFX全屏-根据屏幕大小调整元素的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法使全屏显示(如果可能的话,也可以调整大小),而不是重新排列所有内容(实际上是将诸如调整大小的元素重新排列到整个屏幕)来制作实际的全屏显示模式? (例如通常会更改屏幕分辨率的游戏),以便按钮和文本会随着屏幕/窗口的大小而相应地增长

Is there any way to make fullscreen(and if possible resizing too) to instead of rearranging everything (actually what it does is to rearrange the elements like resizing but to the whole screen) to make an actual fullscreen mode? (like games that what usually do is change screen resolution), so that buttons and text grows accordingly to the size of the screen/window

我该如何删除消息并单击"esc"键退出全屏模式?

Also how can I remove the message and the effect on click the "esc" key to exit the fullscreen mode?

使用这种方法来调整大小

use this way to make resizeable

@Override public void start(Stage stage) throws Exception{
    final int initWidth = 720;      //initial width
    final int initHeight = 1080;    //initial height
    final Pane root = new Pane();   //necessary evil

    Pane controller = new CtrlMainMenu();   //initial view
    controller.setPrefWidth(initWidth);     //if not initialized
    controller.setPrefHeight(initHeight);   //if not initialized
    root.getChildren().add(controller);     //necessary evil

    Scale scale = new Scale(1, 1, 0, 0);
    scale.xProperty().bind(root.widthProperty().divide(initWidth));     //must match with the one in the controller
    scale.yProperty().bind(root.heightProperty().divide(initHeight));   //must match with the one in the controller
    root.getTransforms().add(scale);

    final Scene scene = new Scene(root, initWidth, initHeight);
    stage.setScene(scene);
    stage.setResizable(true);
    stage.show();

    //add listener for the use of scene.setRoot()
    scene.rootProperty().addListener(new ChangeListener<Parent>(){
        @Override public void changed(ObservableValue<? extends Parent> arg0, Parent oldValue, Parent newValue){
            scene.rootProperty().removeListener(this);
            scene.setRoot(root);
            ((Region)newValue).setPrefWidth(initWidth);     //make sure is a Region!
            ((Region)newValue).setPrefHeight(initHeight);   //make sure is a Region!
            root.getChildren().clear();
            root.getChildren().add(newValue);
            scene.rootProperty().addListener(this);
        }
    });
}

推荐答案

有两种方法可以调整UI大小.

There are a couple of ways to resize your UI.

按字体大小缩放

您可以通过在场景样式表的.root中设置-fx-font-size来缩放所有控件.

You can scale all controls by setting -fx-font-size in the .root of your scene's style sheet.

例如,如果将以下样式表应用于场景,则所有控件的大小都会加倍(因为默认字体大小为13px).

For example, if you apply the following stylesheet to your scene, then all controls will be doubled in size (because the default font size is 13px).

.root { -fx-font-size:26像素; }

.root { -fx-font-size: 26px; }

上面的方法可以缩放控件,这对于完全基于控件的对象来说是好的,但是对于基于图形和形状的对象来说不是那么好.

The above will work to scale controls, which is fine for things which are completely control based, but not so good for things which are graphic and shape based.

按变换比例

应用 Scale 转换以(0,0)到场景的根节点.

Apply a Scale transform pivoted at (0,0) to your scene's root node.

Scale scale = new Scale(scaleFactor, scaleFactor);
scale.setPivotX(0);
scale.setPivotY(0);
scene.getRoot().getTransforms().setAll(scale);

要缩放我开发的包含图形和各种形状的游戏,我使用了一种信箱技术,该技术将游戏窗口的大小调整为恒定的纵横比(类似于观看4:3电视节目时看到的信箱)在16:9的屏幕上).

To scale a game I developed which includes graphics and various shapes, I used a letter boxing technique which sized the game window to a constant aspect ratio, (similar to the letter boxing you see when you watch a 4:3 tv show on a 16:9 screen).

下面的代码中的SceneSizeChangeListener侦听场景大小的更改,并根据可用的场景大小缩放场景的内容.

The SceneSizeChangeListener in the code below listens for changes to the scene size and scales the content of the scene appropriate to the available scene size.

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.transform.Scale;
import javafx.stage.Stage;
import org.jewelsea.games.supersnake.layout.LayoutController;

import java.io.IOException;
import java.util.ResourceBundle;

/* Main JavaFX application class */
public class SuperSnake extends Application {
  public static void main(String[] args) { launch(args); }

  @Override public void start(final Stage stage) throws IOException {
    FXMLLoader loader = new FXMLLoader(
        getClass().getResource("layout/layout.fxml"),
        ResourceBundle.getBundle("org.jewelsea.games.supersnake.layout.text")
    );
    Pane root = (Pane) loader.load();

    GameManager.instance().setLayoutController(loader.<LayoutController>getController());

    Scene scene = new Scene(new Group(root));
    stage.setScene(scene);
    stage.show();

    GameManager.instance().showMenu();

    letterbox(scene, root);
    stage.setFullScreen(true);
  }

  private void letterbox(final Scene scene, final Pane contentPane) {
    final double initWidth  = scene.getWidth();
    final double initHeight = scene.getHeight();
    final double ratio      = initWidth / initHeight;

    SceneSizeChangeListener sizeListener = new SceneSizeChangeListener(scene, ratio, initHeight, initWidth, contentPane);
    scene.widthProperty().addListener(sizeListener);
    scene.heightProperty().addListener(sizeListener);
  }

  private static class SceneSizeChangeListener implements ChangeListener<Number> {
    private final Scene scene;
    private final double ratio;
    private final double initHeight;
    private final double initWidth;
    private final Pane contentPane;

    public SceneSizeChangeListener(Scene scene, double ratio, double initHeight, double initWidth, Pane contentPane) {
      this.scene = scene;
      this.ratio = ratio;
      this.initHeight = initHeight;
      this.initWidth = initWidth;
      this.contentPane = contentPane;
    }

    @Override
    public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, Number newValue) {
      final double newWidth  = scene.getWidth();
      final double newHeight = scene.getHeight();

      double scaleFactor =
          newWidth / newHeight > ratio
              ? newHeight / initHeight
              : newWidth / initWidth;

      if (scaleFactor >= 1) {
        Scale scale = new Scale(scaleFactor, scaleFactor);
        scale.setPivotX(0);
        scale.setPivotY(0);
        scene.getRoot().getTransforms().setAll(scale);

        contentPane.setPrefWidth (newWidth  / scaleFactor);
        contentPane.setPrefHeight(newHeight / scaleFactor);
      } else {
        contentPane.setPrefWidth (Math.max(initWidth,  newWidth));
        contentPane.setPrefHeight(Math.max(initHeight, newHeight));
      }
    }
  }
}

这是一个屏幕截图,您可以在其中看到信箱和缩放生效.中间的绿草是主要的游戏内容屏幕,并按比例缩放以适应可用的屏幕区域.如果您正在以与屏幕不同的长宽比观看电视节目,则外部的木质纹理提供了尺寸灵活的边框,该边框填充了黑色字母框通常应位于的区域.请注意,以下截图中的背景在标题页面上是模糊的,因为这样做是为了使游戏开始时,无论大小如何,模糊效果都将消失并且视图清晰.

Here is a screenshot where you can see the letterboxing and scaling taking effect. The green grass in the middle is the main game content screen and scales up and down to fit the available screen area. The wood texture around the outside provides a flexibly sized border which fills in the area where the black letterbox bars would normally be if you were watching a tv program at a different aspect ratio to your screen. Note that the background in the screenshot below is blurry at the title page because I make it so, when the game starts, the blur effect is removed and the view is crisp regardless of the size.

窗口版本:

缩放的全屏版本:

您可能会认为上面的缩放方法可能会使所有内容变得块状和像素化,但事实并非如此.所有字体和控件均可以平滑缩放.所有标准绘图和图形命令以及基于CSS的样式都可以平滑缩放,因为它们都是基于矢量的.即使是位图图像也可以很好地缩放,因为JavaFX在缩放图像时使用了相当高质量的过滤器.

You might think that the scaling method above might make everything go all blocky and pixelated, but it doesn't. All font's and controls scale smoothly. All standard drawing and graphic commands and css based styles scale smoothly as they are all vector based. Even bitmapped images scale well because JavaFX uses fairly high quality filters when scaling the images.

在图像上进行良好缩放的一个技巧是提供高分辨率图像,以便在屏幕放大时,JavaFX系统具有更多可用于处理的原始数据.例如,如果应用程序的首选窗口大小是屏幕大小的四分之一,并且包含一个64x64图标,而使用128x128图标,那么当该应用程序以全屏显示且所有元素都已缩放时,缩放器将具有更多的原始图像.像素数据样本用于插值.

One trick to get good scaling on images is to provide high resolution images, so that when the screen scales up, the JavaFX system has more raw data to work from. For example, if the preferred window size for an app is quarter of the screen size and it contains a 64x64 icon, instead use a 128x128 icon, so that when the app is put in full screen and all elements scaled, the scaler has more raw pixel data samples to use for interpolating values.

由于硬件加速,缩放速度也很快.

The scaling is also fast as it is hardware accelerated.

如何删除消息并单击"esc"键退出全屏模式?

how can I remove the message and the effect on click the "esc" key to exit the fullscreen mode?

在JavaFX 2.2中无法删除全屏退出消息,而在JavaFX 8中则可以:

It's not possible to remove the full screen exit message in JavaFX 2.2, it will be possible in JavaFX 8:

RT-15314允许受信任的应用禁用全屏覆盖警告并禁用退出于ESC"行为

这样做会很好,因为那样我的游戏就不会对他们有看着我-我看起来像Beta"的感觉.

It will be nice when that is done, because then my games won't have that "look at me - I look like a beta" feel about them.

这篇关于JavaFX全屏-根据屏幕大小调整元素的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆