Help us understand the problem. What is going on with this article?

JRubyでJavaFX+FXML

More than 3 years have passed since last update.

お手軽にマルチプラットフォームな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

スクリーンショット 2015-08-13 11.08.17.png

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

ボタンを押すと、テキストフィールドに文字列が表示される。

スクリーンショット 2015-08-13 12.01.09.png

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から渡した文字列が表示される。

スクリーンショット 2015-08-13 13.54.40.png

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

スクリーンショット 2015-08-13 15.41.38.png

FXMLで作った画面にFXMLで作った画面を埋め込む

なんて表現していいか難しいけど、使いどころとしてはTabPaneのTabを動的に増やしたいときなど、結構ある。

JavaFXでNode突っ込むようなところ(TabのsetContentとか、BorderPaneのsetBottomとか)には、コントローラのインスタンスを突っ込んでやればいいっぽい。

そのうち書く
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした