2018/02/27(火) [n年前の日記]
#1 [ruby] FXRubyを勉強中
RubyでGUIアプリが作れる、FXRubyというライブラリについて勉強中。環境は、Window10 x64 + Ruby 2.2.6 p396 mingw32 + fxruby 1.6.39 x86-mingw32。
全然関係ないけど、FXRuby の公式サイトが消滅してるような…?
全然関係ないけど、FXRuby の公式サイトが消滅してるような…?
◎ ハローワールド。 :
まずは、Hello World。
_hellofxruby.rb
実行すると以下のようなウインドウが開く。
ボタンをクリックするとダイアログが表示される。
_hellofxruby.rb
require "fox16" include Fox class MyHello < FXMainWindow def initialize(app, title = "Hello World FXRuby") # main is window class mw = super(app, title, :width => 320, :height => 240) # create layout pack = FXPacker.new(mw) # create label lbl = FXLabel.new(pack, "Hello World !") # create button btn = FXButton.new(pack, "Click !") # set button push event btn.connect(SEL_COMMAND) do |sender, sel, data| # show message box msg = FXMessageBox.new(btn, "Message", "Hello World in FXRuby", :opts => MBOX_OK) msg.execute end end def create super show(PLACEMENT_SCREEN) end end if __FILE__ == $0 FXApp.new do |app| mw = MyHello.new(app) app.create app.run end end
実行すると以下のようなウインドウが開く。
ボタンをクリックするとダイアログが表示される。
◎ 少し解説。 :
FXRuby を使うときは、最初のあたりに、以下の行を書く。
FXMainWindow というクラスが、おそらくはメインウインドウを担当するクラスなのだろう…。継承して、自分用のクラスを作成して、それを使うのが一般的っぽい。
クラスを作ったら、以下のようにして呼び出す…のかな。
メインウインドウに登録できる部品は色々ある。例えば、以下のような感じ。
ただ、各部品をメインウインドウにそのまま登録していくと、縦にずらずら並んでいってしまう。部品のレイアウトには FXPacker を使うらしい…が、それについては後述。
ボタンを押したら何か処理をさせたい、てな場合は、以下のように書けば設定できる模様。
require "fox16" include Fox
FXMainWindow というクラスが、おそらくはメインウインドウを担当するクラスなのだろう…。継承して、自分用のクラスを作成して、それを使うのが一般的っぽい。
class MyMainWindow < FXMainWindow def initialize(app, title = "Hello World FXRuby") mw = super(app, title, :width => 320, :height => 240) # 部品を生成したりイベントを設定したり色々初期化 end def create super show(PLACEMENT_SCREEN) end end
クラスを作ったら、以下のようにして呼び出す…のかな。
FXApp.new do |app| mw = MyMainWindow.new(app) app.create app.run end
メインウインドウに登録できる部品は色々ある。例えば、以下のような感じ。
- FXLabel ... ラベル。文字列を表示できる
- FXButton ... ボタン
- FXTextField ... テキストフィールド。入力欄。
ただ、各部品をメインウインドウにそのまま登録していくと、縦にずらずら並んでいってしまう。部品のレイアウトには FXPacker を使うらしい…が、それについては後述。
ボタンを押したら何か処理をさせたい、てな場合は、以下のように書けば設定できる模様。
btn = FXButton.new(pack, "Click !") btn.connect(SEL_COMMAND) do |sender, sel, data| # show message box msg = FXMessageBox.new(btn, "Message", "Hello World in FXRuby", :opts => MBOX_OK) msg.execute endまだ意味は分かってないけど、とにかくこう書いとけば動くらしい…。ちなみに、上記の例では、ボタンを押すとメッセージボックスが表示される。
◎ 少し複雑なレイアウトをしてみる。 :
各部品を、横方向に並べたり等、それなりにレイアウトしたい。
部品のレイアウトには FXPacker、FXHorizontalFrame、FXVerticalFrame を使う。
ということで、試してみた。
_fileselect_sample.rb
それらしくレイアウトできた。
部品のレイアウトには FXPacker、FXHorizontalFrame、FXVerticalFrame を使う。
- まずは FXPacker をメインウインドウに登録。
- その FXPacker に、FXHorizontalFrame (部品を横並びにしてくれる) や FXVerticalFrame (部品を縦並びにしてくれる) 等のフレームを登録。
- それらフレームに、各部品を登録。
ということで、試してみた。
_fileselect_sample.rb
require "fox16" include Fox class MyMainWindow < FXMainWindow def initialize(app, title = "Generate Tilemap collision data") # main is window class # mw = super(app, title, :width => 480, :height => 360) mw = super(app, title) # create layout # pack = FXPacker.new(mw, :opts => LAYOUT_FILL) pack = FXPacker.new(mw) @frms = [] tbls = [ { :label => "Source Tiled JSON", :type => 0, :len => 50 }, { :label => "Source PNG Image", :type => 0, :len => 50 }, { :label => "Collision layer name", :type => 1, :len => 20 }, { :label => "layer name (overwrite)", :type => 1, :len => 20 }, { :label => "Null code", :type => 1, :len => 5 }, { :label => "Output JSON", :type => 0, :len => 50 }, ] tbls.each_with_index do |dt, i| s = dt[:label] kind = dt[:type] l = dt[:len] # create frame frm = FXHorizontalFrame.new( pack, # :opts => LAYOUT_SIDE_LEFT|LAYOUT_SIDE_TOP|LAYOUT_FIX_WIDTH, #:padLeft=>0,:padRight=>0,:padTop=>0,:padBottom=>0, # :width=>300 ) # create label FXLabel.new(frm, s) # create textfield tf = FXTextField.new(frm, l) case kind when 0 # create button btn = FXButton.new(frm, "...") # set button event btn.connect(SEL_COMMAND) do |sender, sel, data| # show File dialog dialog = FXFileDialog.new(self, "Select file.") dialog.patternList = [ "All Files (*)", "JSON (*.json)", "PNG Image (*.png)", ] dialog.selectMode = SELECTFILE_ANY if dialog.execute != 0 tf.text = dialog.filename end end @frms.push( { :type => kind, :textfield => tf, :button => btn } ) when 1 @frms.push( {:type => kind, :textfield => tf } ) end end @frms[2][:textfield].text = "layer0" @frms[4][:textfield].text = "0" frm = FXHorizontalFrame.new( pack, :opts => LAYOUT_SIDE_RIGHT|LAYOUT_SIDE_TOP, :width => 300, ) sx, sy = 32, 8 btn = FXButton.new(frm, "Check", :padLeft => sx, :padRight => sx, :padTop => sy, :padBottom => sy) btn.connect(SEL_COMMAND) do |sender, sel, data| # dump input string jsonfile = @frms[0][:textfield].text pngfile = @frms[1][:textfield].text layername = @frms[2][:textfield].text layername_s = @frms[3][:textfield].text nullcode = @frms[4][:textfield].text.to_i outfile = @frms[5][:textfield] s = [ "json file : #{jsonfile}", "png file : #{pngfile}", "layer name : #{layername}", "layer name sub : #{layername_s}", "null code : #{nullcode}", "output file : #{outfile}", ].join("\n") msgBox = FXMessageBox.new(btn, "Result", s, :opts => MBOX_OK) msgBox.execute end end def create super show(PLACEMENT_SCREEN) end end if __FILE__ == $0 FXApp.new do |app| mw = MyMainWindow.new(app) app.create # mw.show(PLACEMENT_SCREEN) app.run end end
それらしくレイアウトできた。
◎ ファイル選択ダイアログについて。 :
上記ソースは、ボタンを押すと、ファイル選択ダイアログボックスを表示するようになっている。呼び出してる部分は以下。
FXFileDialog がソレ。拡張子のリストを作成して .patternList に設定したり、選択モードを .selectMode に設定したりしている。
dialog.execute を呼ぶとダイアログが表示されて、選択されたファイルの数が返ってくるのだろう…。0が返ってきたら、何も選択していないか、キャンセルされた、ということではないかと。
.selectMode には、 _Class: Fox::FXFileSelector からすると、以下が指定できる模様。
余談。FXRuby のファイル選択ダイアログを使うと、以下のようなダイアログが表示されるのだけど。
普段見ているダイアログとは、見た目がちょっと違う。
FXRuby が使っている FOX Toolkit は、OSのネイティブのGUI部品やダイアログを使わずに、それぞれを独自実装しているらしいので、こういった部分で違いが出てくるのだろう…。逆に考えると、Windows でも Linux でも似たような見た目になってくれる…はず。
# show File dialog dialog = FXFileDialog.new(self, "Select file.") dialog.patternList = [ "All Files (*)", "JSON (*.json)", "PNG Image (*.png)", ] dialog.selectMode = SELECTFILE_ANY if dialog.execute != 0 tf.text = dialog.filename end
FXFileDialog がソレ。拡張子のリストを作成して .patternList に設定したり、選択モードを .selectMode に設定したりしている。
dialog.execute を呼ぶとダイアログが表示されて、選択されたファイルの数が返ってくるのだろう…。0が返ってきたら、何も選択していないか、キャンセルされた、ということではないかと。
.selectMode には、 _Class: Fox::FXFileSelector からすると、以下が指定できる模様。
- SELECTFILE_ANY ... 1ファイルを選択。もしくはファイル名を指定。ファイルセーブ時に使える。
- SELECTFILE_EXISTING ... 既に存在する1ファイルを選択。ファイルロード時に使える。
- SELECTFILE_MULTIPLE ... 既に存在する複数ファイルを選択。
- SELECTFILE_MULTIPLE_ALL ... 既に存在する複数ファイル、または複数ディレクトリを選択。
- SELECTFILE_DIRECTORY ... 既に存在するディレクトリを選択。
余談。FXRuby のファイル選択ダイアログを使うと、以下のようなダイアログが表示されるのだけど。
普段見ているダイアログとは、見た目がちょっと違う。
FXRuby が使っている FOX Toolkit は、OSのネイティブのGUI部品やダイアログを使わずに、それぞれを独自実装しているらしいので、こういった部分で違いが出てくるのだろう…。逆に考えると、Windows でも Linux でも似たような見た目になってくれる…はず。
◎ ドラッグアンドドロップはどうやるのだろう。 :
エクスプローラ等でファイルを選択して、FXRuby で表示したウインドウにドラッグアンドドロップ(Drag and drop, DND, D&D)することでファイルのパスを取得する、といった処理をしたい。しかし、そんなことできるのだろうか…。*NIX上ではできるけど、Windows上ではできないよ、という話を以前見かけたけれど…。
以下で紹介されてるサンプルを、Windows上で動かしてみた。
_Drag and Drop in Windows with Explorer - Ruby
残念ながら、D&Dしてもマウスカーソルは×マークのままだった。
コレ、Linux上なら動くのかな…? どうなんだろう…?
以下で紹介されてるサンプルを、Windows上で動かしてみた。
_Drag and Drop in Windows with Explorer - Ruby
残念ながら、D&Dしてもマウスカーソルは×マークのままだった。
コレ、Linux上なら動くのかな…? どうなんだろう…?
◎ Ubuntu16.04上でFXRubyのインストールと動作確認。 :
FXRuby を使ったソースが、VMware + Ubuntu 16.04 LTS上でも動作するのか確認してみたい。
Ubuntu上での FXRuby インストール手順を調べたが、パッケージをいくつかインストール後、FOX Toolkit の現行版をDL・ビルドして、最後に sudo gem instal fxruby をしないといかんらしい。
gem install fxruby だけで動いてしまうWindows版と比べると、導入が面倒なのだな…。
必要になるらしいパッケージを apt でインストール。
FOX Toolkit の現行版をDL・ビルド・インストール。
Rubyをインストール。sudo apt install ruby だけでは済まなくて、ruby-full をインストールしないといけない。ruby-full を入れると、Rubyのライブラリをビルドできるようになる模様。
fxruby がビルドされた。ちなみに、何故かドキュメントの生成で異様に時間がかかったので、--no-ri --no-rdoc をつけてドキュメントの生成はスキップさせた。
irb を起動して、require 'fox16' と打ってエラーが出なければ、インストールはできている。
さておき、前述の、 _FXRubyを使ったドラッグアンドドロップのサンプル を、Ubuntu 16.04上で動かしてみたところ、ファイラーからファイルをD&Dすることでファイル群のパスが取得できた。
つまり、*NIX + FXRuby ならドラッグアンドドロップが働くけど、Windows上では働かない模様。不便だ…。
Ubuntu上での FXRuby インストール手順を調べたが、パッケージをいくつかインストール後、FOX Toolkit の現行版をDL・ビルドして、最後に sudo gem instal fxruby をしないといかんらしい。
gem install fxruby だけで動いてしまうWindows版と比べると、導入が面倒なのだな…。
必要になるらしいパッケージを apt でインストール。
sudo apt install g++ sudo apt install libfox-1.6-dev lxrandr libxext-dev libgl1-mesa-dev libglademm-2.4-dev freeglut3-dev libglew1.5-dev
FOX Toolkit の現行版をDL・ビルド・インストール。
mkdir ~/package cd ~/package wget ftp://ftp.fox-toolkit.org/pub/fox-1.6.56.tar.gz tar xvzf fox-1.6.56.tar.gz cd fox-1.6.56 ./configure make sudo make install
Rubyをインストール。sudo apt install ruby だけでは済まなくて、ruby-full をインストールしないといけない。ruby-full を入れると、Rubyのライブラリをビルドできるようになる模様。
sudo apt install ruby-full sudo gem install fxruby --no-ti --no-rdoc
fxruby がビルドされた。ちなみに、何故かドキュメントの生成で異様に時間がかかったので、--no-ri --no-rdoc をつけてドキュメントの生成はスキップさせた。
irb を起動して、require 'fox16' と打ってエラーが出なければ、インストールはできている。
さておき、前述の、 _FXRubyを使ったドラッグアンドドロップのサンプル を、Ubuntu 16.04上で動かしてみたところ、ファイラーからファイルをD&Dすることでファイル群のパスが取得できた。
つまり、*NIX + FXRuby ならドラッグアンドドロップが働くけど、Windows上では働かない模様。不便だ…。
◎ 参考ページ。 :
[ ツッコむ ]
以上です。