Python GUI Spyder と Qt Designer で かんたん GUI 開発
Python と PyQt を使うことで、簡単なGUIユーティリティをつくるのは非常に簡単になった。
のだが、やはりGUIをコードでしこしこかくのは面倒なので、ツールを使いたい。
ということで、PyQt に含まれている、Qt Designer の使い方を覚えようと思う。
ちなみに、配布まで考えると、Portable Python で試した方がよいかと思ったら、今は開発が止まっているようで、WinPython 環境、および 同梱されている、Spyder というIDEを利用してみるが、基本的にはどんな環境でも同じだと思う。
1.Spyder プロジェクトを作成
WinPython をダウンロードインストールすると、ディレクトリに、Spyder.exe があるので、これを起動する。WinPython 自体は、有用なパッケージ(PyQtも含まれている)を含んだ独立したPython環境で、Windows 自体のレジストリなどの環境を基本的には汚染しない。
1.1 Spyderワークスペースの作成
IDE Spyder のプロジェクトを作成する。
メニューから New project。
現在のワークペースが構成されていないから、構成するか?と訪ねられるので YES
ワークスペースとは何かの説明が表示されるので、以下のように理解してOK
Spder のワークスペースは、複数のSpyderプロジェクトや、.spyderworkspace 設定ファイルを含む、ファイルシステム上のディレクトリ。
Spyder プロジェクトは、ソースコード(および関連ファイル)や設定ファイル(.spyderproject) とともに、設定(PYTHONPATH、リンクされたプロジェクトなど)を含むディレクトリ。
指定したディレクトリを、Spyderワークスペースとして構成しますかきかれるので、YES
1.2 Spyder プロジェクトの作成
晴れて、プロジェクトが作成出来るようになったので、プロジェクトエクスプローラー(表示されていない場合、メニュー - View ー Panes) のコンテキストメニューから、New project
プロジェクト名を、gui_sample とでもして、OK
1.3 パッケージの作成
ui ファイル用のパッケージをプロジェクトのコンテキストメニューから、New – Package で作成。ui とでもしておく。ここに、Qt Designer で作成したファイルを置く。
2. Qt Designer でGUIの作成
http://web.eng.hawaii.edu/~bsb/me696_f14/assign/gui_qt4_ex.html
同様に、WinPython のインストールディレクトリの、Qt Designer.exe を起動する
2.2 起動時にウィザードが立ち上がるので、Widgetを選択してみる
適当にコントロールを配置。
Qt Designer 自体の使い方は、Qt Designer使い方入門 がわかりやすい。
以下のように、フォーム上にテキストボックスと、ボタンを2つ配置する
試しに、F4 を押して、シグナル/スロットを編集 モード にし、左下のボタンが押下されたら、テキストを選択状態にするように設定してみる。
オブジェクトの名前をプロパティペインから、
テキストボックス : txt_message
OK ボタン : btn_ok とでもしておく
作成したフォームを保存する。
保存するときに、上記 Spyder で作成した、ui パッケージのディレクトリに保存しておく。
3.UI設定ファイルの変換
Qt Designer で作成した、UIは、XMLのファイルとして作成されるため、これを Python のファイルに変換させる。
GUIは、Qt Designer で作成/編集 を行いたいので、基本的にUIのファイルは編集しないですむように開発環境を整えたい。
ということで、UI XML を Python に変換する Pythonスクリプトを、ui パッケージに配置し、
- Qt Designer で UIを編集 –> 保存
- 変換スクリプト
- 処理をコーディング
という流れにしたい。
以下は、最低限の変換コード、タイムスタンプを比較して自動で変換を走らせたりと、高機能出来そうだが、まずは、今回上記で作成した、ui ファイルを変換させる
ui.convert_qt.py
# -*- coding: utf-8 -*- from PyQt4 import uic fin = open('first_form.ui', 'r') fout = open('first_form.py', 'w') uic.compileUi(fin,fout,execute=False) fin.close() fout.close()
以下が、変換されて生成されたファイル。このファイルに修正を加えても失われちゃうよ!との注意書き。
ui.first_form.py
# -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'first_form.ui' # # Created by: PyQt4 UI code generator 4.11.4 # # WARNING! All changes made in this file will be lost! from PyQt4 import QtCore, QtGui try: _fromUtf8 = QtCore.QString.fromUtf8 except AttributeError: def _fromUtf8(s): return s try: _encoding = QtGui.QApplication.UnicodeUTF8 def _translate(context, text, disambig): return QtGui.QApplication.translate(context, text, disambig, _encoding) except AttributeError: def _translate(context, text, disambig): return QtGui.QApplication.translate(context, text, disambig) class Ui_Form(object): def setupUi(self, Form): Form.setObjectName(_fromUtf8("Form")) Form.resize(368, 140) self.btn_ok = QtGui.QPushButton(Form) self.btn_ok.setGeometry(QtCore.QRect(270, 100, 75, 23)) self.btn_ok.setObjectName(_fromUtf8("btn_ok")) self.txt_message = QtGui.QTextEdit(Form) self.txt_message.setGeometry(QtCore.QRect(20, 20, 331, 71)) self.txt_message.setObjectName(_fromUtf8("txt_message")) self.pushButton_2 = QtGui.QPushButton(Form) self.pushButton_2.setGeometry(QtCore.QRect(20, 100, 75, 23)) self.pushButton_2.setObjectName(_fromUtf8("pushButton_2")) self.retranslateUi(Form) QtCore.QObject.connect(self.pushButton_2, QtCore.SIGNAL(_fromUtf8("clicked()")), self.txt_message.selectAll) QtCore.QMetaObject.connectSlotsByName(Form) def retranslateUi(self, Form): Form.setWindowTitle(_translate("Form", "Form", None)) self.btn_ok.setText(_translate("Form", "OK", None)) self.pushButton_2.setText(_translate("Form", "Select", None))
4. 実行スクリプトの作成
アプリケーションを実行する スクリプトを作成する。main.py とでもして、プロジェクト直下に作成すると、以下のような構成になる。
上記で作成したUIを呼び出し、処理をバインドするコードを記述する。
構成に工夫の余地はあるが、Qt Desinger で作成した、UIを利用する Formを宣言することで、見た目と処理コードが分離(ボタンを押下したときの処理を、btn_ok_clicked() に記述し、初期化時にバインド)でき、継続的にUIを変更するサイクルも整った。
# -*- coding: utf-8 -*- import sys from PyQt4 import QtCore, QtGui from ui import first_form class MyForm(QtGui.QMainWindow): def __init__(self,parent=None): QtGui.QWidget.__init__(self, parent) self.ui = first_form.Ui_Form() self.ui.setupUi(self) QtCore.QObject.connect(self.ui.btn_ok,QtCore.SIGNAL("clicked()"), self.btn_ok_cliked) def btn_ok_cliked(self): print type(self.ui) self.ui.txt_message.setText("Hello, Qt") def run_app(): app = QtGui.QApplication(sys.argv) form = MyForm() form.show() sys.exit(app.exec_()) if __name__ == '__main__': run_app()
5.実行
実行すると、ダイアログが立ち上がり、OKボタンを押下で、メッセージが表示され、Select ボタンで、メッセージを全選択されることが確認できた!!!