[入門]PyQtでHello Worldを表示する

PythonのGUIプログラミングの一つであるPyQtを使ってみます。

# 環境
・macOS
・python 3.6.4
・PyQt 5.12.1

# Qt DesignerでGUI作成
Qt Designerは[Anaconda](https://www.anaconda.com/)をインストールしていれば同梱されています。私の場合、~/anaconda3/bin/Designerにありました。あるいは、[Qt](https://www.qt.io/jp/download_short?hsCtaTracking=8bafc666-8621-4048-8a87-9b8f44e7555e%7C70337833-1874-4f45-a9e7-c4c753eecc5a)をインストールしても使えるようになります。

Qt Designerを立ち上げると、以下のような画面が出てきます。templates/formsのMain Windowを選択し、右下の作成ボタンを押します。

![スクリーンショット 2019-04-27 16.36.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404447/4627db7c-93dc-cac3-cc6f-fc7c31e5b463.png)

編集画面が立ち上がります。ウィジェットボックスウィンドウにある各種ウィジェットをドラッグ&ドロップすることでGUIを作っていくことができます。今回は簡単に、ラベルとボタンを一つずつ配置した画面を作成します。最終的に、ボタンを押すとラベルに「Hello World」と表示されるようにします。

![スクリーンショット 2019-04-27 16.50.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404447/df0c023f-dbbd-2591-0b7a-337247a07620.png)

![スクリーンショット 2019-04-27 16.50.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404447/ced37a04-4874-a510-2c9e-5645d00af046.png)

　続いてボタンを押した場合のイベントを設定します。Qtには[Signal/Slot](https://doc.qt.io/archives/qt-4.8/signalsandslots.html)という仕組みがあります。ボタンを押すとSignalが放出され、紐づけられた受け手のSlot(関数)が呼ばれる、といったイメージでしょうか。
　Designerで「編集」->「シグナル/スロットの編集」を選択します。次に、先ほど配置したボタンを選択し適当な場所にドラッグ&ドロップすると以下のようになると思います。

![スクリーンショット 2019-04-27 17.12.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404447/76cf56b3-828d-0a55-2c28-5663b35b0673.png)

また、以下のような画面が立ち上がります。

![スクリーンショット 2019-04-27 17.13.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404447/112c1a76-9689-795f-5a0c-b549056552fa.png)

左側の選択肢内の「pressed」を選択することで、ボタンが押された時にSignalが飛ぶようになります。右側のSlotは空欄ですので、「編集...」ボタンを押して、自分で関数を登録します。
以下のような画面が出てくると思います。

![スクリーンショット 2019-04-27 18.04.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404447/6cee15a4-2901-d274-996e-ea2666a58f7d.png)

上部のスロットの「+」ボタンを押して関数を追加します。名前は「setTextHelloWorld()」としておきます。関数の中身は後ほど実装します。関数を追加したら、右下の「OKボタン」を押してウィンドウを閉じます。
先ほどの画面に戻ると、右側のスロットに、追加した「setTextHelloWorld()」が登録されています。こちらを選択し、「OKボタン」を押します。
これで、ボタンを押した時に関数「setTextHelloWorld()」が呼ばれるようになります。

![スクリーンショット 2019-04-27 18.09.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404447/08132242-0262-6974-8844-7ee3d81189a0.png)

![スクリーンショット 2019-04-27 18.15.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404447/e4580751-64a9-e913-b160-14ace06a3ca6.png)

ここまでできたら、ファイルを保存します。名前は「hello_world.ui」としておきます。

# .uiファイルを.pyファイルに変換
PyQt5をインストールしてない方はまず、pipでインストールします。
`$pip install PyQt5`

先ほど作成した「hello_world.ui」を「hello_world_ui.py」という名前で、Pythonスクリプトに変換します。
`$pyuic5 hello_world.ui > hello_world_ui.py`
これで、以下のようなPythonスクリプトができます。

```python:hello_world_ui.py

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(400, 300)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(160, 40, 60, 16))
        self.label.setObjectName("label")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(140, 90, 110, 30))
        self.pushButton.setObjectName("pushButton")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 400, 22))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.pushButton.pressed.connect(MainWindow.setTextHelloWorld)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label.setText(_translate("MainWindow", "TextLabel"))
        self.pushButton.setText(_translate("MainWindow", "PushButton"))

```

# 機能ファイルを作成
続いて、UIと機能を分けるために、「hello_world_gui.py」ファイルを作成します。内容は以下のようになります。

```python:hello_world_gui.py
import sys

from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QMainWindow

from hello_world_ui import Ui_MainWindow


class HelloWorldGui(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(HelloWorldGui, self).__init__(parent)
        self.setupUi(self)

    @pyqtSlot()
    def setTextHelloWorld(self):
        self.label.setText("Hello World")


if __name__ == '__main__':
    argvs = sys.argv
    app = QApplication(argvs)
    hello_world_gui = HelloWorldGui()
    hello_world_gui.show()
    sys.exit(app.exec_())

```

「HelloWorldGui」クラスがhello_world_ui.pyの「Ui_MainWindow」を継承する形になります。__init__関数内で親クラスのsetupUi()関数を呼び出すことでUIのセットアップをしています。
また、setTextHelloWorld()関数では、QLabelが持つsetText()メソッドを用いて、ラベルにHello Worldをセットしています。

# 動かしてみる

実際に起動します。
`$python hello_world_gui.py`

<img width="402" alt="スクリーンショット 2019-04-27 19.25.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404447/3892c71f-baeb-b3af-4884-b10badaee5ef.png">

ボタンを押すと、

<img width="402" alt="スクリーンショット 2019-04-27 19.17.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404447/7b14f999-c6f5-ae53-4d04-f48571b9461c.png">