GTK+のシステムトレイのテストのコードをVala言語に移植
Gtk#のコードをもとにしてValaのコードを作成
「Gtk#でシステムトレイを使用してメニューを表示する」のコードをもとにしてGTK+のシステムトレイのテストのコードをValaに移植してみた。
using Gtk; namespace ValaSystrayTest { /* * 継承の記述はC#と同様で、多重継承ができないのも同じ * また、同様にインターフェースが使用可能となっている */ class TrayMenu : Gtk.Menu // Gtk.Menuを継承 { Gtk.ImageMenuItem item1; Gtk.ImageMenuItem item2; Gtk.ImageMenuItem item3; Gtk.ImageMenuItem item_quit; Gtk.StatusIcon trayicon; public TrayMenu (Gtk.StatusIcon trayicon) { /* * ストックアイコン付きメニュー項目を作成する流れ * メンバ変数imageには * ストックアイコンとサイズを指定したGtk.Imageオブジェクトを指定 * 「with_xxx」「from_xxx」などで生成するときにも「new」が必要 * (これらはコンストラクタとなっている) */ this.trayicon = trayicon; this.item1 = new Gtk.ImageMenuItem.with_label ("item1"); this.item1.image = new Gtk.Image.from_stock (Gtk.STOCK_PREFERENCES, Gtk.IconSize.MENU); this.item2 = new Gtk.ImageMenuItem.with_label ("item2"); this.item2.image = new Gtk.Image.from_stock (Gtk.STOCK_OPEN, Gtk.IconSize.MENU); this.item2.sensitive = false; // 選択できない状態にする this.item3 = new Gtk.ImageMenuItem.with_label ("item3"); this.item3.image = new Gtk.Image.from_stock (Gtk.STOCK_CLOSE, Gtk.IconSize.MENU); this.item_quit = new Gtk.ImageMenuItem.from_stock (Gtk.STOCK_QUIT, null); /* * 下の形式ではGtk.AccelGroupオブジェクトを作成後 * 2番目の引数に指定するとストックアイコンと「Ctrl+Q」のような文字列が付く */ //Gtk.AccelGroup group = new AccelGroup (); //this.item_quit = new Gtk.ImageMenuItem.from_stock (Gtk.STOCK_QUIT, group); // 閉じようとすると落ちる? /* 項目を追加していく */ this.append (this.item1); // 本クラスのメンバ関数(継承したappend())を呼んでいる this.append (this.item2); this.append (this.item3); this.append (new Gtk.SeparatorMenuItem ()); // 分割線 this.append (this.item_quit); /* 表示可能にする */ this.show_all (); /* * シグナルの設定はC#に近いが右辺にはハンドラ名のみを指定 */ /* トレイアイコンの通常クリック時にon_item1_activated()を呼ぶ */ this.trayicon.activate += this.on_item1_activated; /* 各項目が選択されたときのハンドラを設定 */ this.item1.activate += this.on_item1_activated; this.item2.activate += this.on_item2_activated; this.item3.activate += this.on_item3_activated; this.item_quit.activate += this.on_item_quit_activated; } void on_item1_activated () { print ("item1 activated\n"); } void on_item2_activated () { this.item2.sensitive = false; // item2を選択できなくする this.item3.sensitive = true; // item3を選択できるようにする this.trayicon.blinking = false; // 点滅状態を解除 print ("item2 activated\n"); } void on_item3_activated () { this.item2.sensitive = true; this.item3.sensitive = false; this.trayicon.blinking = true; // 点滅開始 print ("item3 activated\n"); } void on_item_quit_activated () { Gtk.main_quit (); // メインループ終了 } } class ValaSystrayTest { TrayMenu menu; Gtk.StatusIcon icon; public void main (string[] args) { Gtk.init (ref args); // 初期化 this.icon = new Gtk.StatusIcon.from_stock (Gtk.STOCK_DIALOG_INFO); /* tooltip_text,tooltip_markupはGTK+ 2.16以上が必要・tooltipは利用不可 */ // this.icon.tooltip_text = "test"; // マウスポインタを少し乗せたときに出る文字列 //this.icon.tooltip = "test"; // .vapiファイルを修正すれば使用可能 this.menu = new TrayMenu (this.icon); this.icon.popup_menu += this.on_popup; // ポップアップイベント Gtk.main (); // メインループ開始 } void on_popup (uint button, uint activate_time) { /* * システムトレイアイコンの位置に合わせてメニューをポップアップする */ this.menu.popup (null, null, icon.position_menu, button, activate_time); } } class MainClass { public static void main (string[] args) { ValaSystrayTest app = new ValaSystrayTest (); app.main (args); } } }
(2009/5/10)Gtk.ImageMenuItem.with_label()などのコンストラクタに関する一部コメントの微調整
(2009/5/22)「this」が使用できるところで全て「this」を記述、メッセージ出力関数の微調整
シグナル接続
シグナルの接続に関する操作はGtk#のときに近い書式で「+=」の演算子を用いてハンドラを指定(追加)する。ただし、C#とは違って「new FooHandler ([ハンドラ])」のように指定するのではない点に注意。
/* トレイアイコンの通常クリック時にon_item1_activated()を呼ぶ */ this.trayicon.activate += this.on_item1_activated; /* 各項目が選択されたときのハンドラを設定 */ this.item1.activate += this.on_item1_activated; this.item2.activate += this.on_item2_activated; this.item3.activate += this.on_item3_activated; this.item_quit.activate += this.on_item_quit_activated;
問題点
システムトレイアイコンのツールチップ指定
Gtk.StatusIconオブジェクトのメンバ変数tooltipを
icon.tooltip = "test";
のように変更しようとしても
error: The name `tooltip' does not exist in the context of `Gtk.StatusIcon' icon.tooltip = "test"; ^^^^^^^^^^^^ Compilation failed: 1 error(s), 0 warning(s)
というエラーになる。調べると代わりに「tooltip_text」あるいは「tooltip_markup」を用いることができることが分かったのだが、これらはバージョン2.16系以上のGTK+を要求してしまう。
これを回避するには、古い名前の(非推奨な)関数での呼び出しができるようにするという方法がある。Valaコード側で
icon.tooltip = "test";
のように記述しておいて.vapiファイルのGtk.StatusIconクラスの中に
ファイル名: vala-0.7.1/vapi/gtk+-2.0.vapi
public void set_tooltip (string text); public string tooltip { get; set; }
を記述するとビルドも通り動作もする。ただ、GTK+ 2.16以上が主流になる頃にはこのようにはせずに「_text」「_markup」付きのバージョンを使用するようにしたほうがよい。
ストックアイコン付きのメニュー項目でGtk.AccelGroupを使用すると選択時に落ちる?
システムトレイのメニューでは意味がないが、「閉じる」のメニュー項目について「Ctrl+Q」を出すためにGtk#のときと同様に
Gtk.AccelGroup group = new AccelGroup (); this.item_quit = new Gtk.ImageMenuItem.from_stock (Gtk.STOCK_QUIT, group); // 閉じようとすると落ちる?
と書いたところ、メニューには「Ctrl+Q」が表示されるようになったのだが、これを選択すると落ちてしまった。対処方法は不明なのでこの件に付いては保留とする。
関連記事:
使用したバージョン:
- Vala 0.7.1
- GTK+ 2.14.3