Tk と Tkx の違い(ActivePerl Win32)
Windows版 ActivePerl 5.10.0 から Tk がバンドルされなくなった。
俗にいう Perl/Tk ではなくなった。
これは、暗にGUIはTkxで書けということなのかもしれない。
TkxはGUI版のPPMでも使われている便利なモジュールである。
では、TkとTkxの違いはなんだろうか?
これは、Tkが新しいTkモジュールが開発されるたびにPerlのTkモジュールを書き直す必要があることを示している。これに対して、TkxはTcl/Tk経由でTkを呼び出しているため、Tcl/Tkで使用できるモジュールは、Tkxですべて使用可能ということになる。その代り、Perlの他にTcl/Tkが必要になる。しかし、Windows 版のActivePerlでは、ActiveTclをインストールしなくてもTkxが使用できる。これは、tkkitモジュールがバンドルされているためである。tkkitは小さなTcl/Tkの役割をする。したがって、ActivePerlさえインストールされていれば、Tclモジュールを使って簡単なTcl/Tkプログラムを実行できる。調べてみると、Windows版のPythonでもTkinterを使って似たような実装をしているようだ。
次は文法の話。概念的にはTkを使うことに変わりないのだけれど、文法やモジュールの呼び出し方法が微妙に違う。これはPerl/Tkで書いたプログラムの移行の妨げになる。
以下はTkの場合:
以下はTkxの場合:
これでは既存のプログラムを移行する気にはなれない。
最後にモジュール依存関係の違い。これは、実装の違いから明白である。Tkは自己完結しているのに対してTkxはTcl/Tkを必要とする。
これはPAR::Packerを使ってPerl/TkプログラムをEXE化して配布していた人には大きな問題である。つまり、Tkxで書いたプログラムを次のコマンドでとEXE化しても、
EXEを実行すると次のようなメッセージが出て実行できない。
このエラーはTkxで使っているインターフェース用のモジュールTcl.pmで呼び出しているTcl.DLLがTcl/Tkを見つけられないことによって生じる。
この件に関しては、いろいろ試してみたが、Tcl/Tkの実装によほど詳しくなければ解決できそうにない。
ちなみに、回避方法として、ActiveTcl をインストールしておくという手もある。しかし、それでは、Perl を EXE にまとめた意味がない。
そんなわけで、Perl/Tk から Tkx への移行は難しい。しばらくは、Tkモジュールを使用し続けることになりそうだ。
追記: この件については解決法が判明した。詳細は「PerlでTkxを使ったプログラムをPAR::PackerでExe化する」を参照
俗にいう Perl/Tk ではなくなった。
これは、暗にGUIはTkxで書けということなのかもしれない。
TkxはGUI版のPPMでも使われている便利なモジュールである。
では、TkとTkxの違いはなんだろうか?
- 実装方法が違う
- 文法が違う
- モジュールの依存関係が違う
- TkはTkライブラリをXSで呼び出している。
- TkxはTclモジュール経由でTcl/Tkを使いTkライブラリを呼び出している。
これは、Tkが新しいTkモジュールが開発されるたびにPerlのTkモジュールを書き直す必要があることを示している。これに対して、TkxはTcl/Tk経由でTkを呼び出しているため、Tcl/Tkで使用できるモジュールは、Tkxですべて使用可能ということになる。その代り、Perlの他にTcl/Tkが必要になる。しかし、Windows 版のActivePerlでは、ActiveTclをインストールしなくてもTkxが使用できる。これは、tkkitモジュールがバンドルされているためである。tkkitは小さなTcl/Tkの役割をする。したがって、ActivePerlさえインストールされていれば、Tclモジュールを使って簡単なTcl/Tkプログラムを実行できる。調べてみると、Windows版のPythonでもTkinterを使って似たような実装をしているようだ。
次は文法の話。概念的にはTkを使うことに変わりないのだけれど、文法やモジュールの呼び出し方法が微妙に違う。これはPerl/Tkで書いたプログラムの移行の妨げになる。
以下はTkの場合:
use utf8;
use Tk;
my $mw = new MainWindow;
$mw->Button(-text=>'こんにちは',-command=>sub{exit})->pack;
MainLoop;
以下はTkxの場合:
use utf8;
use Tkx;
my $mw = Tkx::widget->new(".");
$mw->new_button( -text => "こんにちは",
-command => sub{$mw->g_destroy})->g_pack;
Tkx::MainLoop();
これでは既存のプログラムを移行する気にはなれない。
最後にモジュール依存関係の違い。これは、実装の違いから明白である。Tkは自己完結しているのに対してTkxはTcl/Tkを必要とする。
これはPAR::Packerを使ってPerl/TkプログラムをEXE化して配布していた人には大きな問題である。つまり、Tkxで書いたプログラムを次のコマンドでとEXE化しても、
pp -o TkxHello.exe TkxHello.pl
EXEを実行すると次のようなメッセージが出て実行できない。
Could not access registry "HKLM\Software\ActiveState\ActiveTcl"
Could not access registry "Software\ActiveState\ActiveTcl" CurrentVersion
Failed to load Tcl dll! at C:/Perl/lib/DynaLoader.pm line 224.
Unable to initialize Tcl at C:/Perl/lib/DynaLoader.pm line 224.
Compilation failed in require at Tkx.pm line 206.
BEGIN failed--compilation aborted at Tkx.pm line 206.
Compilation failed in require at script/TkxHello.pl line 2.
BEGIN failed--compilation aborted at script/TkxHello.pl line 2.
このエラーはTkxで使っているインターフェース用のモジュールTcl.pmで呼び出しているTcl.DLLがTcl/Tkを見つけられないことによって生じる。
この件に関しては、いろいろ試してみたが、Tcl/Tkの実装によほど詳しくなければ解決できそうにない。
ちなみに、回避方法として、ActiveTcl をインストールしておくという手もある。しかし、それでは、Perl を EXE にまとめた意味がない。
そんなわけで、Perl/Tk から Tkx への移行は難しい。しばらくは、Tkモジュールを使用し続けることになりそうだ。
追記: この件については解決法が判明した。詳細は「PerlでTkxを使ったプログラムをPAR::PackerでExe化する」を参照
この記事へのコメント