試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

PyGTKで、ショートカットキーにより、テキストラベルに関連付けた別のウィジェットをフォーカスする

GTK+では、1行テキスト入力ボックス(gtk.Entry)の隣に説明の文字列(gtk.Label)を配置するようなときに、この入力ボックスをフォーカスするためのショートカットキーをラベルのほうに表示*1し、Altキーを押しながら指定されたキーを押すことで対象のGUI部品(ウィジェット)がフォーカスされるようにすることが比較的簡単に行える。

例(Gladeを使用しない場合)

[任意]ファイル名: mnemonictest.py

#! /usr/bin/python
# -*- encoding: utf-8 -*-

import sys
import os
try:
  import pygtk
  pygtk.require("2.0")
except:
  pass
try:
  import gtk
except:
  sys.exit(1)

class PyGTKMnemonicTest:
  """
  ニーモニック・ウィジェットのテスト
  """
  def __init__(self):
    # ウィンドウ
    self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
    self.window.set_title("mnemonic widget test")

    # ショートカットキー(アクセラレータ)
    self.accelgroup = gtk.AccelGroup()
    self.window.add_accel_group(self.accelgroup)

    # メニューバー項目
    self.menuitem = gtk.MenuItem("_File", True)
    self.imagemenuitem = gtk.ImageMenuItem(gtk.STOCK_QUIT, self.accelgroup)
    self.gtkmenu = gtk.Menu()
    self.gtkmenu.add(self.imagemenuitem)
    self.menuitem.set_submenu(self.gtkmenu)
    self.menubar = gtk.MenuBar()
    self.menubar.append(self.menuitem)

    # このテストのメイン部分
    # ラベルとテキスト・エントリのペア(水平ボックスでまとめる)を2つ作り
    # 垂直ボックスでメニューと一緒にまとめる
    self.entry1 = gtk.Entry()
    self.entry1.set_text("Alt + L")
    self.entry2 = gtk.Entry()
    self.entry2.set_text("Alt + M")
    # コンストラクタで文字列指定をしてset_use_underline()を呼ぶ
    self.label1 = gtk.Label("_label")
    self.label1.set_use_underline(True)  # 下線をニーモニックウィジェットのために使用
    self.label1.set_mnemonic_widget(self.entry1)
    # コンストラクタでの文字列指定 + set_use_underline()の代わりに
    # set_markup_with_mnemonic()も使用できる
    self.label2 = gtk.Label()
    self.label2.set_markup_with_mnemonic("markup with _mnemonic")
    self.label2.set_mnemonic_widget(self.entry2)
    # 以下はレイアウト構成
    self.hbox1 = gtk.HBox(False, 0)
      # ラベルとエントリを横に並べる
    self.hbox1.pack_start(self.label1, False, False, 0)
    self.hbox1.pack_start(self.entry1, True, True, 0)  # エントリを最大化
    self.hbox2 = gtk.HBox(False, 0)
    self.hbox2.pack_start(self.label2, False, False, 0)
    self.hbox2.pack_start(self.entry2, True, True, 0)
      # ウィンドウ全体を縦に分割
    self.vbox = gtk.VBox(False, 0)
    self.vbox.pack_start(self.menubar, False, True, 0)
    self.vbox.pack_start(self.hbox1, True, True, 0)
    self.vbox.pack_start(self.hbox2, True, True, 0)
    self.hbox1.set_border_width(10)
    self.hbox2.set_border_width(10)
    self.window.add(self.vbox)

    # シグナルを手動で接続
    self.imagemenuitem.connect("activate", gtk.main_quit)
    self.window.connect("delete_event", gtk.main_quit)

    # 表示
    self.window.show_all()
  def main(self):
    gtk.main()

if __name__ == "__main__":
  app = PyGTKMnemonicTest()
  app.main()

動作

この例では、2つの「テキストラベル(文字列)とテキスト入力ボックス(テキストエントリ)」のペアがウィンドウ上に配置されていて、上のラベルでは「l」、下のラベルでは「m」にそれぞれ下線が付いている。

上下それぞれのペアでラベルとエントリは対応付けられていて、

  • Alt+Lで上のテキストエントリ
  • Alt+Mで下のテキストエントリ

がそれぞれフォーカスされるようになっている。

関連付け方

上と下のペアでは、少しだけ違った手順をとっている。
上のほうでは、ラベルの文字列をコンストラクタ引数から指定*2後、gtk.Labelオブジェクトのメンバ関数set_use_underline()で下線をアクセラレータキーとして使用するように指示している。
下では、set_markup_with_mnemonic()関数に(下線を含んだ)文字列を渡している。この場合はset_use_underline()は不要。
そのどちらかを行った状態でメンバ関数set_mnemonic_widget()に対象ウィジェットのオブジェクトを渡すことで、関連付けが完了する。

Gladeでは簡単

Gladeを使用する場合、GtkLabelの「全般」タブに「ニーモニックウィジェット」という項目がある。ここで関連付けたいウィジェットを選択すればよい。

参考URL:

使用したバージョン:

  • Glade 3.4.4

*1:Altキーと一緒に押すキーの文字に下線を付ける形

*2:「self.label1 = gtk.Label("_label")」の部分・これだけでは下線がそのまま「下線」として表示されてしまう