2013-05-17 289 views
11

有什麼辦法全屏顯示(如果可能的話調整過)的,而不是重新安排一切(實際上它的作用是像調整,但整個畫面中的元素重新排列)至做一個實際的全屏模式? (比如通常做的是改變屏幕分辨率的遊戲),以便按鈕和文本根據屏幕/窗口的大小相應增長JavaFX的全屏 - 縮放元素根據屏幕大小

另外,如何刪除消息和效果後單擊「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); 
     } 
    }); 
} 

回答

14

有一對夫婦的方式來調整你的UI。

規模的字體大小

您可以在場景中的樣式表的.root設置-fx-font-size縮放所有控件。

例如,如果您應用以下樣式表到場景中,然後所有的控件將規模擴大了一倍(因爲默認字體大小爲13像素)。

.root { -fx-字體大小:26px; }

上述內容將對控件進行縮放,這對於完全基於控件的事物來說是很好的,但對於基於圖形和形狀的事物來說並不那麼好。

規模由變換

套用Scale變換(0,0)旋轉到場景的根節點。

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

要縮放遊戲我開發,其中包括圖形和各種形狀,我使用的信拳擊技術,其尺寸遊戲窗口,以恆定的高寬比,(類似於字母拳擊時看到觀看4 :在16:9屏幕上播放3個電視節目)。下面

代碼的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和縮放生效。中間的綠草是主要的遊戲內容屏幕,並且可以上下縮放以適應可用的屏幕區域。外繞木材紋理提供了填補了區裏的黑色黑邊,通常是如果你在不同的寬高比屏幕觀看電視節目的可靈活大小的邊界。需要注意的是在下面的截圖的背景是在扉頁模糊,因爲我讓它如此,當比賽開始時,模糊效果被移除,無論大小的觀點是清晰的。

窗口版本:

letterbox

縮放全屏版本:

letterbox-full-screen

你可能會認爲,上述調整方法可能使諸事所有塊狀和像素化,但它不「T。所有字體和控件都可以平滑地縮放。所有標準圖形和圖形命令以及基於CSS的樣式都可以平滑地縮放,因爲它們都是基於矢量的。即使位圖圖像也能很好地縮放,因爲JavaFX在縮放圖像時使用相當高質量的濾鏡。

一招,以獲得良好的圖像縮放是提供高分辨率圖像,這樣,當屏幕比例增加,JavaFX的系統已經更多的原始數據從工作。例如,如果應用程序的首選窗口大小是屏幕大小的四分之一,並且它包含一個64x64圖標,而使用一個128x128圖標,那麼當應用程序放在全屏幕中並縮放所有元素時,縮放器的生像素數據採樣用於內插值。

縮放也快,因爲它是硬件加速。

我怎樣才能刪除消息和效果點擊「ESC」鍵退出全屏模式?

這是不可能在JavaFX的2.2卸下全屏退出消息,它將在JavaFX的8可能:

RT-15314 Allow trusted apps to disable the fullscreen overlay warning and disable the "Exit on ESC" behavior

這將是很好的時候做到這一點,因爲那時我的遊戲不會有「看我 - 我看起來像一個測試版」的感覺。

+0

非常感謝你,嘗試了一下代碼,似乎工作,即使我沒有想到,使用全屏將是那個麻煩和困難... – user1090694

+0

略有修改聽衆的代碼,但更改根寬度/高度不起作用,所以當場景比原始場景增大時,根元素就會到達場外,但是當場景變小時,不會覆蓋整個場景,能否幫助我解決這個問題?該代碼是在以下鏈接:http://codepaste.net/cm5jzn(場景我初始化以下方式場景s =新場景(新控制器()),其中控制器擴展窗格(可以改變,因爲我改變窗格); – user1090694

+0

對不起,您的解決方案比我有點不同,我真的不能調試它爲你,可是我放在一起的[信拳擊片段的可執行例如,從這個帖子(HTTPS://gist.github。 COM/jewelsea/5603471)的情況下,可以幫助你。祝你好運:-) – jewelsea

3

「還我怎麼能刪除該郵件和點擊效果‘ESC’鍵退出全屏模式?」

使用此代碼:

stage.setFullScreenExitHint(""); 

它將改變字符串消息「按Esc退出全屏模式」爲空字符串,這樣就不會出現。