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

参考ページ。 :

#2 [ruby] Ruby-GNOME2を試用

Window + FXRuby ではファイルのドラッグアンドドロップが働かないと分かったので、別のGUIライブラリならどうかなと。例えば Ruby/GTK2 だか Ruby-GNOME2 ならどうだろうと。

このライブラリ、正式名称が分からんのだけど…。公式サイトでは「Ruby-GNOME2」と書いてあるから、それが正しいのだろうか?

_Ruby-GNOME2 Project Website - Ruby-GNOME2 Project Website

インストール。 :

Windows10 x64 + Ruby 2.3.3 p222 mingw32版でインストールしてみた。

gem install gtk2
> gem install gtk2
Fetching: pkg-config-1.2.9.gem (100%)
Successfully installed pkg-config-1.2.9
Fetching: native-package-installer-1.0.6.gem (100%)
Successfully installed native-package-installer-1.0.6
Fetching: cairo-1.15.11-x86-mingw32.gem (100%)
Successfully installed cairo-1.15.11-x86-mingw32
Fetching: glib2-3.2.1-x86-mingw32.gem (100%)
Successfully installed glib2-3.2.1-x86-mingw32
Fetching: atk-3.2.1-x86-mingw32.gem (100%)
Successfully installed atk-3.2.1-x86-mingw32
Fetching: cairo-gobject-3.2.1-x86-mingw32.gem (100%)
Successfully installed cairo-gobject-3.2.1-x86-mingw32
Fetching: gobject-introspection-3.2.1-x86-mingw32.gem (100%)
Successfully installed gobject-introspection-3.2.1-x86-mingw32
Fetching: pango-3.2.1-x86-mingw32.gem (100%)
Successfully installed pango-3.2.1-x86-mingw32
Fetching: gio2-3.2.1-x86-mingw32.gem (100%)
Successfully installed gio2-3.2.1-x86-mingw32
Fetching: gdk_pixbuf2-3.2.1-x86-mingw32.gem (100%)
Successfully installed gdk_pixbuf2-3.2.1-x86-mingw32
Fetching: gtk2-3.2.1-x86-mingw32.gem (100%)
Successfully installed gtk2-3.2.1-x86-mingw32
Parsing documentation for pkg-config-1.2.9
Installing ri documentation for pkg-config-1.2.9
Parsing documentation for native-package-installer-1.0.6
Installing ri documentation for native-package-installer-1.0.6
Parsing documentation for cairo-1.15.11-x86-mingw32
Installing ri documentation for cairo-1.15.11-x86-mingw32
Parsing documentation for glib2-3.2.1-x86-mingw32
Installing ri documentation for glib2-3.2.1-x86-mingw32
Parsing documentation for atk-3.2.1-x86-mingw32
Installing ri documentation for atk-3.2.1-x86-mingw32
Parsing documentation for cairo-gobject-3.2.1-x86-mingw32
Installing ri documentation for cairo-gobject-3.2.1-x86-mingw32
Parsing documentation for gobject-introspection-3.2.1-x86-mingw32
Installing ri documentation for gobject-introspection-3.2.1-x86-mingw32
Parsing documentation for pango-3.2.1-x86-mingw32
Installing ri documentation for pango-3.2.1-x86-mingw32
Parsing documentation for gio2-3.2.1-x86-mingw32
Installing ri documentation for gio2-3.2.1-x86-mingw32
Parsing documentation for gdk_pixbuf2-3.2.1-x86-mingw32
Installing ri documentation for gdk_pixbuf2-3.2.1-x86-mingw32
Parsing documentation for gtk2-3.2.1-x86-mingw32
Installing ri documentation for gtk2-3.2.1-x86-mingw32
Done installing documentation for pkg-config, native-package-installer, cairo, glib2, atk, cairo-gobject, gobject-introspection, pango, gio2, gdk_pixbuf2, gtk2 after 11 seconds
11 gems installed
gtk2 3.2.1 x86-mingw32 がインストールされた。

動作には、以下も必要らしい。自動でインストールしてくれる。
  • pkg-config
  • native-package-installer
  • cairo
  • glib2
  • atk
  • cairo-gobject
  • gobject-introspection
  • pango
  • gio2
  • gdk_pixbuf2

ファイルのドラッグアンドドロップ。 :

以下の記事で、ドラッグアンドドロップを使った事例が紹介されてる。

_Ruby Window Drop: いち雑記

ソースをコピペして、Windows10 x64 + Ruby 2.3.3 p222 mingw32 上で動作確認。エクスプローラから、ウインドウにD&Dしたところ…ファイルのパスが表示された。素晴らしい。

つまり、Ruby-GNOME2 なら、Windows上でもファイルのD&Dでファイルパスを取得できるようだなと。

FXRuby と比べると、ウインドウが表示されるまで結構待たされる印象を受けたけど。しかし、その分、高機能、ということになるのだろう…。たぶん。

以上、1 日分です。

過去ログ表示

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