こんにちは。
昨年12月のJavaFX Advent Calendarで果たせなかった(詳しくはこちら)、JavaFXのHiDPI対応をやってみました。まずは出来上がりから。
yumix/javafx-dpi-scaling · GitHub
実はちゃんとしたテストをしていないのですが、ローンチ・カスタマーの @btnrouge が彼の会社の製品に適用したところ全然問題なかったというので、それなりに動くとは思っています。
アプリケーションから使うのは基本的には org.yumix.javafx.scaling パッケージ、その中でも Scaling クラスになります。
package hidpi; import org.yumix.javafx.scaling.Scaling; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.scene.layout.AnchorPane; import javafx.stage.Stage; public class AppMain extends Application { @Override public void start(Stage stage) throws Exception { AnchorPane root = FXMLLoader.load(getClass().getResource("Sample.fxml")); // Scaling.getDefault() でインスタンスを取得 // Scaling.compute(root) で root とその子のサイズを解像度に合わせて調整 Scene scene = new Scene(Scaling.getDefault().compute(root)); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
現状、まだShapeに対応していないとか、テストほとんどやっていないとか、課題は残っていますが、根となるPaneを指定するだけでよろしくやってくれるようになりました。
今回やったことは、javafx.scene.Nodeと既知のすべてのサブクラスについて、スケーリングの影響がありそうな位置、サイズ、マージン、パディングに関するプロパティの値を補正するようなプログラムを組んで、それを再帰呼び出しでノードのツリー全体に適用するようにしたことです。この調査自体は私でなく @btnrouge がやってくれたのですが、彼が送ってくれた実装があまりにひどかった(全部staticメソッドにしていた)ので、調査結果だけ拝借して私が全部作り直しました。
(GlassFishユーザー会の副会長さんが、まさか全部staticのC言語みたいなJavaプログラムを送ってくるとは思わなかったよ…)
次回は、Shape対応が終わったころに、設計みたいなことをまとめようと思ってます。
ではでは。