我們在開發桌面程式時,對於視窗的放大縮小一直都不好控制,畫面一旦複雜起來,在縮放的過程中常常容易跑版。
於是就想說,如果可以像遊戲一樣,對整個畫面進行等比放大,那就會方便許多。
以下方法就是類似於遊戲整體放大方法,我們先以一個預設解析度來設計UI,最後讓者個畫面有等比縮放功能。
1.建立畫面架構
我們需要一個以GridPane為根的底,然後塞入一層AnchorPane。
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.layout.*?> <GridPane fx:id="gp_test" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="768.0" prefWidth="1366.0" stylesheets="@../css/style.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.lugia.controllers.TestActivityController"> <columnConstraints> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" /> </columnConstraints> <rowConstraints> <RowConstraints minHeight="10.0" vgrow="SOMETIMES" /> </rowConstraints> <children> <AnchorPane fx:id="ap_test" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="768.0" prefWidth="1366.0" GridPane.halignment="CENTER" GridPane.valignment="CENTER" /> </children> </GridPane>
在GridPane中,主要需要設定好寬高,以pref參數為主,其他min與max的寬高度都設為USE_PREF_SIZE
在AnchorPane中,要設定valignment與halignment為CENTER,如上面程式碼。
接下來就可以在AnchorPane中放入自己的元件了。
2.畫面的main程式設定
package com.lugia; import com.lugia.controllers.MainActivityController; import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.scene.layout.Pane; import javafx.scene.transform.Scale; import javafx.stage.Stage; public class MainActivity extends Application { private MainActivityController controller; @Override public void start(Stage primaryStage) throws Exception{ //反鋸齒 System.setProperty("prism.lcdtext", "false"); FXMLLoader fxmlLoader = new FXMLLoader(getClass().getClassLoader().getResource("fxml/main_activity.fxml")); Pane root = fxmlLoader.load(); primaryStage.setTitle("Test"); Scene scene = new Scene(root); primaryStage.setScene(scene); primaryStage.show(); //視窗顯示確定大小後,再做最小尺寸限制 primaryStage.setMinWidth(primaryStage.getWidth()); primaryStage.setMinHeight(primaryStage.getHeight()); controller = fxmlLoader.getController(); letterbox(scene, root); // primaryStage.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; //如須能縮小,則設為0(或一個最小的倍數) if (scaleFactor >= 1) { Scale scale = new Scale(scaleFactor, scaleFactor); //如需要中心放大,則使用(newWidth/2),(newHeight/2),測試用的root元件為GridPane,Alignment設為TOP_LEFT,第二層為AnchorPane,V/Halignment設為CENTER scale.setPivotX(newWidth/2); scale.setPivotY(newHeight/2); 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)); } } } public static void main(String[] args) { launch(args); } @Override public void stop() { controller.onClose(); } }
3.執行效果
原始大小(約1366*768):
畫面放到最大(約1920*1080):注意頂部TITLE跟畫面UI的比例,視窗整個放大後不會跑版
-END-
發佈留言