2016/01/19

PyQtでGUI:.uiファイルのload

PyQt(PyQt4)でGUIプログラムする自分用メモ

.uiファイル+Qt Designerが使いやすいのもQtのメリットだと思ってるのでpythonからもUIのレイアウトはこれでやりたい。

.uiでレイアウトしてpythonで読み込むには2つ方法があるらしい。

  1. pyuic4を使って.ui -> .pyに変換しimport
  2. uicを使って直接import

1.は.pyに統一できていいが、開発中は毎UI変更の度に変換が必要でめんどい。 2.は変換は不要だが.uiファイルをPackageに含まないといけない(それでもいい場合もある?)。 ↓によると開発中は2.でお手軽に、配布時に1.で変換するみたいのが良いってことかな?
https://riverbankcomputing.com/pipermail/pyqt/2010-September/027970.html

というわけでサンプル作ってみた。

まずQt Designerで簡単なUI(PushButtonを押すと、Labelの文字が変わるというだけ)を作成

.uiファイルをloadして表示するコードが以下。

import sys

from PyQt4 import QtCore, QtGui, uic

# form classを直接importする場合は必要
#from ui_mainwindow import Ui_MainWindow

class testPyQt(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        # form classを直接importする場合は↓の行が不要になる
        Ui_MainWindow = uic.loadUiType("ui_mainwindow.ui", self)[0]

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # setup connection
        self.ui.pushButton.clicked.connect(self.onClickButton)

    @QtCore.pyqtSlot()
    def onClickButton(self):
        self.ui.label.setText("Pushed!!")

def main():
    app = QtGui.QApplication(sys.argv)
    window = testPyQt()
    window.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

testPyQtクラスのself.uiにform class(C++ではUi::MainWindowClassとかでmoc_*.cppファイルに生成されてたやつだと思う)をnewする。

検索するとtestPyQtクラス自体をform classから継承する例や、self.uiにuic.loadUi()で生成されたQMainWindow(or QWidget)を直接showするコード(下記)もあったというか結構多い。

前者はUIと制御コードが一緒のclassになっちゃうので避けたい実装、後者はtestPyQtでQMainWindowを継承している意味がわかんなくなるので、その辺のやり方を避けると上のやり方に落ち着きそう。

class testPyQt(QtGui.QMainWindow):
    def __init__(self):
    # uic.loadUi returns QMainWindow
    self.ui = uic.loadUi("ui_mainwindow.ui")
    self.ui.show()

def main():
    app = QtGui.QApplication(sys.argv)
    window = testPyQt()
    # window.show() # ここでshowしない
    sys.exit(app.exec_())

結果、こんな感じにできる。


0 件のコメント: