2012年2月15日水曜日

はじめての PySide with Qt Designer

1年半くらい前に,人力で対応するにはちょっと手間のかかる作業を Python でスクリプト化して提供したことがあるのだが,いかにも間に合わせという感じのする CUI ベースのプログラムで,率直に言って,CUI としてもちょっとどうかと思う UI の代物だった。

ところがつい最近,紆余曲折あってこのプログラムを第三者に提供するということになり,急遽,できるだけ手をかけずに GUI を用意する必要が出てきた(まともなドキュメントを用意するには相手のスキルレベルの確認から始めなくてはならず――要するに考えるのも面倒で僕はその選択肢を放棄した)。

そんな個人的ないきさつも手伝って,この機会に以前から関心のあった PySide を使ってみることにした。PyQt4 にしなかったのはライセンスの都合もあるが,僕が天の邪鬼だからというのも理由の半分だ。天の邪鬼ついでに,チュートリアルで説明されているようなコードだけでゴリゴリと書く方法ではなく,Qt Designer を使った開発を試みた。

ターゲット環境が Windows なので,開発環境にも Windows を使用する。意外な感じがするが,Windows 環境では Python 本体と PySide の2つがあればとりあえず必要なものはそろう。最初はそうと知らずに Qt SDK をインストールしたが,この記事の内容を試すだけならまったく必要ない

ということで,まずはダウンロードページにあるリンクをたどって,Windows 用のバイナリーを取得・インストールしよう。Qt Designer(と Qt Linguist)は PySide の一部としてインストールされる。site-packages*1 の中を覗いてみるといい。

それでは本題に入るとしよう。本家のチュートリアルをなぞるだけだというのもつまらないので,ここでは題材をよそから借りてきて,ボタンをクリックすると "Hello, ~!" と挨拶するプログラムを作る。

では早速 Qt Designer(designer.exe)を起動しよう。新規フォームを作成するダイアログが表示されるので,ここでは "Dialog without Buttons" を選択し,[Create]ボタンをクリックしてまっさらなダイアログを作成する。

すると,右のような画面が表示される。

ここで,作成したダイアログの objectNameHelloDialog に変更する(この名前は後で自動生成するコードのクラス名に反映される)。

次に,Line EditLabelPush Button をダイアログ上に適当に配置する。せっかく(?)なので,題材のオリジナルに倣って Line Edit と Label の水平アラインメントを AlignHCenter に,Push Button の text を "Hello" に変更しておこう。


これで見た目上必要なものは配置できたので,作成した UI をひとまず保存しておこう。ここではファイル名を ui_hellodialog.ui として保存した。

続いて,ui ファイルを(Script*2 フォルダにある)pyside-uic.exe を使って Python のコードに変換する。コマンドプロンプトを開いて以下の通り実行。
pyside-uic -o ui_hellodialog.py ui_hellodialog.ui
説明は不要な気もするが,一応。-o オプションは出力ファイルの指定,その後ろは入力ファイルの指定だ。

今度は hellodialog.py というファイルを以下の内容で作成する。
# -*- coding: utf-8 -*-

import sys

from PySide import QtGui
from ui_hellodialog import Ui_HelloDialog

class HelloDialog(QtGui.QWidget):
    def __init__(self, parent=None):
        super(HelloDialog, self).__init__(parent)
        self.ui = Ui_HelloDialog()
        self.ui.setupUi(self)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    dlg = HelloDialog()
    dlg.show()
    sys.exit(app.exec_())
短いコードだし,なんらかの GUI プログラミング経験があれば察しはつきそうだが,.NET Framework の Windows フォームを引き合いに出して簡単に説明しておくと,
  • ui_hellodialog.py は Visual Studio が自動生成する Form.Designer.cs に相当する。
  • HelloDialog の __init__() は Form クラスのコンストラクタに相当する。
  • 12行目の setupUi() は Form のコンストラクタ内の InitializeComponent() に相当する。
  • 15行目~18行目は Program.cs の内容に相当する。
といったあたりだろう。実行して,ダイアログが表示されることを確認したら次に進もう。

さて,題材に倣ってボタンをクリックしたら "Hello, ~!" とラベルに表示したいわけだが,ここでいったん Designer に戻る。

メニューまたはツールバーから,編集モードを "Edit Signals/Slots" に変更し,ダイアログに配置したボタンをドラッグする。ボタンから(シグナルとスロットを接続する)線が現れるので,ダイアログ上の何もない場所でリリースする。

右図のダイアログが表示されるので,HelloDialog グループの下にある[Edit]をクリックして,HelloDialog のスロットを編集する。

Slots グループボックスの下にある[+]ボタンをクリックして,(ダイアログ上にある Hello ボタンのクリックに対応する)スロットを追加する。ここでは,sayHello() とした。

ひとつ前の画面に戻り,pushButton の clicked() と HelloDialog の sayHello() を選択して[OK]する。HelloDialog 側のリストが有効にならない場合は clicked() をクリックし直すとよい(うまくいかないようなら,一度ほかの項目をクリックしてから clicked() を選び直す)。

これで,シグナル clicked() とスロット sayHello() が接続された。変更内容を保存してから pyside-uic を実行して ui_hellodialog.py を更新しよう。

最後に,hellodialog.py に Designer で追加したスロット sayHello() に対応するメソッドを追加する。5行目でインポートするモジュールが増えているので注意!
# -*- coding: utf-8 -*-

import sys

from PySide import QtCore, QtGui
from ui_hellodialog import Ui_HelloDialog

class HelloDialog(QtGui.QWidget):
    def __init__(self, parent=None):
        super(HelloDialog, self).__init__(parent)
        self.ui = Ui_HelloDialog()
        self.ui.setupUi(self)

    @QtCore.Slot()
    def sayHello(self):
        name = self.ui.lineEdit.text()
        if name:
            self.ui.label.setText('Hello, {0}!'.format(name))
        else:
            self.ui.label.setText('Hello, World!')

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    dlg = HelloDialog()
    dlg.show()
    sys.exit(app.exec_())
14行目~20行目が追加した部分だ。追加したスロットに対応したメソッドだというのが一目瞭然にしてわかるだろう。
メソッド名が Python の慣習的命名規則から外れているけど,Qt の命名規則との兼ね合いの問題になってしまうので,ここは大目に見ておくことにしよう。

というわけで,急場しのぎでちょっとした GUI が必要になったときには割と手軽に使えそうだ。ただし,フォーム/ダイアログに配置するウィジェットをサブクラス化して独自の実装を追加したいなどと言い出すと途端に面倒になりそうなので,深入りはしない予定。

【注記】
  1. あなたの使っているのが Python 2.7 でデフォルト構成でインストールしたのなら,C:\Python27\Lib\site-packages\PySide-1.1.0qt474-py2.7-win32.egg\PySide に探しているものがある。
  2. 上と同じ条件なら,C:\Python27\Scripts\pyside-uic.exe。ところで,Mac OS X で MacPorts を使って PySide をインストールする場合,pyside-uic は py-pyside ではなく py-pyside-tools にあるので注意(これまた最初気づかなくて首をひねった)。Qt Designer 等は qt4-mac の一部としてインストールされる。

0 コメント:

コメントを投稿