有没有办法让全屏(如果可能还要调整大小)而不是重新排列所有内容(实际上它的作用是重新排列元素,如调整大小但是整个屏幕)来制作实际的全屏模式? (比如通常做的游戏就是改变屏幕分辨率),这样按钮和文字会根据屏幕/窗口的大小而增长
另外如何删除信息和效果点击“esc”键退出全屏模式?
编辑:使用这种方式制作可调整大小的
@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);
}
});
}
答案 0 :(得分:14)
有两种方法可以调整用户界面的大小。
按字体大小缩放
您可以通过在场景样式表的-fx-font-size
中设置.root
来缩放所有控件。
例如,如果将以下样式表应用于场景,则所有控件的大小都会加倍(因为默认字体大小为13px)。
.root { -fx-font-size:26px; }
以上内容适用于缩放控件,这对于完全基于控件的内容来说很好,但对于基于图形和形状的内容则不太好。
按比例缩放
将以(0,0)为中心的Scale变换应用于场景的根节点。
Scale scale = new Scale(scaleFactor, scaleFactor);
scale.setPivotX(0);
scale.setPivotY(0);
scene.getRoot().getTransforms().setAll(scale);
为了扩展我开发的包括图形和各种形状的游戏,我使用了一种字母拳击技术,它将游戏窗口的大小调整为恒定的宽高比(类似于你在观看4:3电视节目时看到的字母装箱在16:9的屏幕上。)
下面代码中的SceneSizeChangeListener侦听场景大小的变化,并缩放适合可用场景大小的场景内容。
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));
}
}
}
}
这是一个截图,您可以在其中看到letterboxing和缩放生效。中间的绿草是主要的游戏内容屏幕,可以向上和向下缩放以适应可用的屏幕区域。外部周围的木质纹理提供了一个灵活大小的边框,如果您正在以与屏幕不同的宽高比观看电视节目,则该边框会填充黑色信箱条通常所在的区域。请注意,下面屏幕截图中的背景在标题页上是模糊的,因为我这样做,当游戏开始时,模糊效果被移除,视图清晰无论大小。
加窗版:
缩放全屏版本:
您可能认为上面的缩放方法可能会使所有内容都变得块状和像素化,但事实并非如此。所有字体和控件都可以平滑地缩放。所有标准绘图和图形命令以及基于CSS的样式都可以平滑缩放,因为它们都是基于矢量的。甚至位图图像也可以很好地扩展,因为JavaFX在缩放图像时使用了相当高质量的滤镜。
在图像上获得良好缩放的一个技巧是提供高分辨率图像,以便在屏幕放大时,JavaFX系统可以使用更多原始数据。例如,如果应用程序的首选窗口大小是屏幕大小的四分之一并且它包含64x64图标,而是使用128x128图标,那么当应用程序全屏显示并且所有元素都缩放时,缩放器具有更多原始图标用于插值的像素数据样本。
由于硬件加速,缩放也很快。
如何删除信息及效果点击“esc”键退出全屏模式?
无法在JavaFX 2.2中删除全屏退出消息,它可以在JavaFX 8中使用:
完成后会很好,因为那时我的游戏不会“看着我 - 我看起来像一个测试版”对他们的感觉。
答案 1 :(得分:3)
“另外如何删除消息和效果点击”esc“键退出全屏模式?”
使用此代码:
stage.setFullScreenExitHint("");
它会将字符串消息“按Esc退出全屏模式”更改为空字符串,因此不会显示。
答案 2 :(得分:0)
您可以将其放入JavaFXApplication
Dimension resolution = Toolkit.getDefaultToolkit().getScreenSize();
double width = resolution.getWidth();
double height = resolution.getHeight();
double w = width/1280; //your window width
double h = height/720; //your window hight
Scale scale = new Scale(w, h, 0, 0);
root.getTransforms().add(scale);