web-dev-qa-db-ja.com

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);
        }
    });
}
13
user1090694

UIのサイズを変更するには、いくつかの方法があります。

フォントサイズで拡大縮小

シーンのスタイルシートの-fx-font-size.rootを設定すると、すべてのコントロールをスケーリングできます。

たとえば、次のスタイルシートをシーンに適用すると、すべてのコントロールのサイズが2倍になります(デフォルトのフォントサイズが13pxであるため)。

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

上記は、コントロールをスケーリングするために機能します。これは、完全にコントロールベースであるものには適していますが、グラフィックやシェイプベースのものにはあまり適していません。

変換によるスケール

Scale (0,0)でピボットされた変換をシーンのルートノードに適用します。

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

私が開発したグラフィックとさまざまな形状を含むゲームをスケーリングするために、ゲームウィンドウのサイズを一定のアスペクト比にするレターボクシングテクニックを使用しました(16で4:3テレビ番組を見るときに表示されるレターボクシングと同様です) :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));
      }
    }
  }
}

これは、レターボックスとスケーリングの効果を確認できるスクリーンショットです。中央の緑の芝生はメインのゲームコンテンツ画面であり、利用可能な画面領域に合わせて拡大および縮小します。外側のウッドテクスチャは、画面とは異なるアスペクト比でテレビ番組を視聴している場合に通常黒いレターボックスバーが表示される領域を塗りつぶす柔軟なサイズの境界線を提供します。以下のスクリーンショットの背景はタイトルページでぼやけていることに注意してください。なぜなら、ゲームを開始すると、ぼかし効果が削除され、サイズに関係なくビューがくっきりと見えるようにするためです。

ウィンドウ版:

letterbox

フルスクリーンバージョンのスケーリング:

letterbox-full-screen

上記のスケーリング方法では、すべてがブロック状になり、ピクセル化される可能性があると思うかもしれませんが、そうではありません。すべてのフォントとコントロールはスムーズに拡大縮小します。すべての標準の描画およびグラフィックコマンドとcssベースのスタイルはすべてベクトルベースであるため、スムーズにスケーリングされます。 JavaFXは画像を拡大縮小するときにかなり高品質のフィルターを使用するため、ビットマップ画像でも適切に拡大縮小されます。

画像を適切にスケーリングするための1つの秘訣は、高解像度の画像を提供することです。これにより、画面が拡大したときに、JavaFXシステムはより多くの生データを処理できます。たとえば、アプリの優先ウィンドウサイズが画面サイズの4分の1で、64x64アイコンが含まれている場合は、代わりに128x128アイコンを使用します。これにより、アプリが全画面で表示され、すべての要素が拡大縮小されると、スケーラーの生値の補間に使用するピクセルデータサンプル。

ハードウェアアクセラレーションであるため、スケーリングも高速です。

どうすればメッセージを削除でき、「esc」キーをクリックしてフルスクリーンモードを終了したときの効果を削除できますか?

JavaFX 2.2では全画面終了メッセージを削除することはできません。JavaFX8では可能です。

RT-15314信頼できるアプリが全画面オーバーレイ警告を無効にし、「ESCで終了」動作を無効にすることを許可する

それが完了すると、それは素晴らしいことになります。それは、私のゲームには「私を見て-私はベータ版のように見える」という感覚がないためです。

15
jewelsea

「また、どのようにしてメッセージを削除し、「esc」キーをクリックしてフルスクリーンモードを終了する効果を削除できますか?」

このコードを使用してください:

stage.setFullScreenExitHint("");

「Escキーを押してフルスクリーンモードを終了します」という文字列メッセージを空の文字列に変更して、表示されないようにします。

3
Ratul Bin Tazul

これを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 height
Scale scale = new Scale(w, h, 0, 0);
root.getTransforms().add(scale);
0