お手軽にマルチプラットフォームなGUIアプリを作れそうなので、ちょっと調べてみた。
元がJavaなので面倒なところは面倒だけど、それなりにお手軽。
全コードは下記においてある。
https://github.com/kinumi/jruby-javafx-samples
sample1. ウインドウを表示してみる
ウインドウを表示するだけ。
特に役には立たないけど、お手軽。
sample1/Gemfile
source 'https://rubygems.org/'
gem 'jrubyfx'
gem 'jrubyfx-fxmlloader'
sample1/main.rb
#!jruby
#coding: utf-8
require 'bundler'
Bundler.require
class Main < JRubyFX::Application
def start(stage)
stage.show
end
end
Main.launch
sample2. FXMLで画面を作る
FXMLはJavaFX Scene Builderで作るとお手軽。そのへんは省略。
sample2/ui/hello_window.fxml
省略
FXMLに対応したコントローラを作る。
内容はこんな感じ。
sample2/ui/hello_window.rb
#coding: utf-8
class HelloWindow
include JRubyFX::Controller
# 対応するFXMLファイルを、main.rbで設定したfxml_rootからの相対パスで指定する
fxml 'hello_window.fxml'
# FXMLのイベントハンドラと同名のメソッドを作っておくと勝手に呼んでくれる
def on_hello_action
# FXMLでfx:idを付与したノードはインスタンス変数として参照できる
@txt_hello.text = 'Hello JRuby + JavaFX!!'
end
end
main.rbはこんな感じ。
sample2/main.rb
#!jruby
#coding: utf-8
require 'bundler'
Bundler.require
# FXMLを「ui」ディレクトリ以下から探すよう設定する
fxml_root File.dirname(__FILE__) + '/ui'
# コントローラ
require_relative 'ui/hello_window'
class Main < JRubyFX::Application
def start(stage)
# stageに表示するfxmlを指定する
stage.fxml HelloWindow
stage.show
end
end
Main.launch
ボタンを押すと、テキストフィールドに文字列が表示される。
sample3. コントローラの初期化時にパラメータを渡す
こんなかんじでパラメータを渡せるっぽい。
sample3/ui/hello_window.rb
#coding: utf-8
class HelloWindow
include JRubyFX::Controller
fxml 'hello_window.fxml'
# コンストラクタを定義しておく
def initialize(initial_text)
@txt_hello.text = initial_text
end
def on_hello_action
@txt_hello.text = 'Hello JRuby + JavaFX!!'
end
end
sample3/main.rb
#!jruby
#coding: utf-8
require 'bundler'
Bundler.require
fxml_root File.dirname(__FILE__) + '/ui'
require_relative 'ui/hello_window'
class Main < JRubyFX::Application
def start(stage)
# :initializeというオプションに、コントローラのコンストラクタに渡したい引数を配列で指定する
stage.fxml HelloWindow, :initialize => ['click button ->']
stage.show
end
end
Main.launch
こんな感じで、main.rbから渡した文字列が表示される。
sample4. TableViewを使う
これを使えると結構便利。
sample4/ui/table_view_window.rb
#coding: utf-8
class TableViewWindow
include JRubyFX::Controller
fxml 'table_view_window.fxml'
# Javaのクラスを参照するためのモジュール
# ほんとは共通モジュール的なところで定義するとよさげ
# サンプルなので適当にここで定義する
module J
include_package 'javafx.beans.property'
end
# コンストラクタ
def initialize
# テーブルに表示する内容
# JavaのObservableListを設定する
@table.items = FXCollections.observable_list([])
# Columnごとに、CellValueFactoryを設定する
# JavaのサンプルではPropertyValueFactoryを使っていることが多いが、
# JRubyだとうまくいかない。lambdaやProc.newなどで、自前で実装してやる必要があった
# (もっとうまいやりかたがあるかもしれない。。)
@col_name.cell_value_factory = lambda {|v| v.value.name }
@col_address.cell_value_factory = lambda {|v| v.value.address }
@col_tel.cell_value_factory = lambda {|v| v.value.tel }
# とりあえずダミーデータを1000件分登録してみる
Faker::Config.locale = :ja
1000.times do
name = Faker::Name.name
address = Faker::Address.state + ' ' + Faker::Address.city + ' ' + Faker::Address.building_number
tel = Faker::PhoneNumber.phone_number
@table.items << TableRecord.new(name, address, tel)
end
end
# テーブル1レコードぶんのデータクラス
class TableRecord
attr_reader :name
attr_reader :address
attr_reader :tel
def initialize(name, address, tel)
@name = J::SimpleStringProperty.new(name)
@address = J::SimpleStringProperty.new(address)
@tel = J::SimpleStringProperty.new(tel)
end
end
end
FXMLで作った画面にFXMLで作った画面を埋め込む
なんて表現していいか難しいけど、使いどころとしてはTabPaneのTabを動的に増やしたいときなど、結構ある。
JavaFXでNode突っ込むようなところ(TabのsetContentとか、BorderPaneのsetBottomとか)には、コントローラのインスタンスを突っ込んでやればいいっぽい。
そのうち書く