mieki256's diary



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 の公式サイトが消滅してるような…?

ハローワールド。 :

まずは、Hello World。

_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_ss01.png

ボタンをクリックするとダイアログが表示される。

fxruby_ss02.png

少し解説。 :

FXRuby を使うときは、最初のあたりに、以下の行を書く。
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 ... テキストフィールド。入力欄。
_File: README - Documentation for fxruby (1.6.39) の左の一覧を眺めると、色んな種類があるようで。

ただ、各部品をメインウインドウにそのまま登録していくと、縦にずらずら並んでいってしまう。部品のレイアウトには 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 を使う。
  1. まずは FXPacker をメインウインドウに登録。
  2. その FXPacker に、FXHorizontalFrame (部品を横並びにしてくれる) や FXVerticalFrame (部品を縦並びにしてくれる) 等のフレームを登録。
  3. それらフレームに、各部品を登録。

ということで、試してみた。

_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

fxruby_ss03.png

それらしくレイアウトできた。

ファイル選択ダイアログについて。 :

上記ソースは、ボタンを押すと、ファイル選択ダイアログボックスを表示するようになっている。呼び出してる部分は以下。
          # 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_ss04.png

普段見ているダイアログとは、見た目がちょっと違う。

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上なら動くのかな…? どうなんだろう…?

Ubuntu16.04上でFXRubyのインストールと動作確認。 :

FXRuby を使ったソースが、VMware + Ubuntu 16.04 LTS上でも動作するのか確認してみたい。

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上では働かない模様。不便だ…。

参考ページ。 :


以上です。

過去ログ表示

Prev - 2018/02 - Next
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project