【Python入門】PyQt5でGUIを作ろう!導入から使い方まで解説

PythonでGUIアプリケーションを作成したい
PyQtの導入方法について知りたい
PyQtの使い方について詳しく知りたい

みなさんこんにちは、PythonにてたくさんのGUIを作成してきたGUIマスターのかいです。

今日はPythonのGUIフレームワークであるPyQt5についての使い方を説明していこうと思います。この記事ではPyQt5の導入方法から、チェックボックスの中身を出力するGUIアプリケーション作り方を初心者でもわかるように解説していきます。

この記事を読んでいただければ、PyQtの概要から導入方法、使い方までわかるので、PyQtを使ってGUIを作ってみようと考えている方はぜひ参考にしていただければ幸いです!

  • PyQtとは何か
  • PyQtのメリットデメリット
  • PyQtの導入
  • PyQtの基本的な使い方
  • PyQtにて実際にGUIを作成する

PyQtの記事はいくつかありますが、まだ多くはなく、その中でもチェックボックスによる分岐について書いてある記事はないので、この記事でわかりやすく説明していきます。

なお、Pythonの記事については、こちらにまとめています。

目次

PythonのPyQtとは

まず、PyQtとは何かということについて触れていきます。PyQtとは、クロスプラットフォームなGUIアプリケーションを作るためのフレームワークです。

クロスプラットフォームとは環境に依存せずMacでもWindowsでもLinuxでも個別の対応をしなくても動くということです。PyQtの2019年現在最新VerはPyQt5となります。

そもそもGUIって何?という方もいると思うので解説しておきます。

GUIとは?

GUI(Graphical User Interface)とは視覚的に操作することのできるUIのことです。みなさんがいつも使っているデスクトップなども代表的なGUIですね。

対をなす言葉がCUI(character user interface)と呼ばれるもので、Macでいうターミナル、Windowsでいうコマンドプロプントに相応します。

例えばデスクトップで右クリックをして、フォルダを作成すればGUIによる作成ですし、ターミナルを開いてmkdirコマンドによって作成すればCUIによる作成です。

PyQtのメリット・デメリット

メリット

GUI化するメリットは、もちろん見やすいことです。プログラマの我々であれば、コードに変更を加えてターミナルで実行すれば良いですが、非エンジニアの方に触ってもらうときはGUIの方が親切ですよね。

他にGUI化するメリットは何回も実行コマンドを打たなくて良いことですね。例えば、毎回不規則な値を入れて、何回も実行するプログラミングがあったとしたら、毎回その値の引数を書き換えて実行するのは大変ですよね。

GUIを被せてしまえばGUI上で値を変えたりすることができるので楽です。

デメリット

デメリットは重いことです。他にもCUIに慣れている人はCUIの方が使いやすいなどもありますが、1にも2にもデメリットは重いことです。

通常GUIはC++などで書くことが多いですが、Pythonで書こうと思ったらやはり重いです。とはいえ、複雑すぎなければ我慢できるレベルであり、実用的と言える範囲です。

PyQtを導入しよう

さて、ざっくりPyQtについて、分かったと思うので、導入方法について見ていきます。今回扱うのはQtの最新verのPyQt5ですので間違えないようにしてください。

※今回はMacのターミナルを使用して解説していきます。

導入方法といっても簡単で、

pip install SIP
pip install PyQt5

※Python3系がデフォルトになっていない場合は”pip3”

この2つのコマンドを叩いてももらえれば大丈夫です。

因みにpythonのデフォルトのバージョンは、以下のコマンドで確認できます。

python --version

SIPとはC++プログラムをpythonで利用できるようにするものです。詳しく理解する必要はないのでとりあえず導入しておきましょう。

PyQtでGUIを作成しよう

さて、PyQtの導入が終わったので実際にコードを見ながらPyQtを理解していきましょう。

基本構造を理解しよう

まずは、コードから見てみましょう。

import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sip

class MainWindow(QWidget):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.setGeometry(300, 50, 400, 350)
        self.setWindowTitle('QCheckBox')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())


実行結果

こちらが、テンプレとも言える大元のコードです。見ての通りメイン関数で、main_windowにインスタンスを作って、showメソッドにて表示させています。showメソッドのようにPyQtはフレームワークなので様々な内部メソッドがあります。

気になる方は公式ドキュメントなどに一通り目を通しておくと良いでしょう。

次にsetGeometryメソッドでGUIのサイズを決めています。中の値を変更することでGUIの大きさが変わります。setWindowTitleメソッドでGUIのタイトルを決めています。

チェックボックスを作成しよう

それでは実際にGUIの中にチェックボックスを作っていきます。チェックボックスを作る関数はQCheckBoxです。

def __init__(self, parent=None):
    super(MainWindow, self).__init__(parent)

    self.test = QCheckBox('test', self)
    self.setGeometry(300, 50, 400, 350)
    self.setWindowTitle('QCheckBox')


実行結果

前後は割愛していますが、コンストラクタの中をこのように変更してやればよいですね。チェックボックスができチェックを入れたり外したりできるはずです。

グループ化しよう

次にチェックボックスのグループ化についてみていきます。

def __init__(self, parent=None):
    super(MainWindow, self).__init__(parent)

    # 一つ目のチェックボックス
    self.upper = QCheckBox('大文字', self)
    self.upper.move(100, 30)

    # 二つ目のチェックボックス
    self.lower = QCheckBox('小文字', self)
    self.lower.move(180, 30)

    # グループ化
    self.group = QButtonGroup()
    self.group.addButton(self.upper,1)
    self.group.addButton(self.lower,2)

    self.setGeometry(300, 50, 400, 350)
    self.setWindowTitle('QCheckBox')


実行結果

コンストラクタの中身をこのように変更してみました。チェックボックスを2つ用意したことはわかると思うのですが、ここミソなのはQButtonGroup()というところです。

本来チェックボックスは複数選択できますが、このようにグループ化することによって、グループ内では複数のチェックを入れることができません。実際の現場ではよく使うので覚えておきましょう。

レイアウトを覚えよう

今度はレイアウトについてみていきましょう。分かり易いようにグループ化を解除してチェックボックス一つにして見てみます。新規に関数なども追加したのでコードの全容を見ていきます。

import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sip

class MainWindow(QWidget):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        # 一つ目のチェックボックス
        self.upper = QCheckBox('大文字', self)
        self.upper.move(100, 30)
        self.upper.stateChanged.connect(self.uppercase)

        # 横のレイアウト
        self.horizon = QHBoxLayout()
        # 縦のレイアウト
        self.vertical = QVBoxLayout()

        self.horizon.addLayout(self.vertical)
        self.setLayout(self.horizon)

        self.setGeometry(300, 50, 400, 350)
        self.setWindowTitle('QCheckBox')

    def uppercase(self):
        if(self.upper.isChecked()):
            self.upper_a = QCheckBox('A', self)
            self.vertical.addWidget(self.upper_a)

            self.upper_b = QCheckBox('B', self)
            self.vertical.addWidget(self.upper_b)
        else:
            self.vertical.removeWidget(self.upper_a)
            self.vertical.removeWidget(self.upper_b)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())


実行結果

PyQtにはレイアウトが2つあり、QHBoxかQVBoxがあります。変数名を見てわかるとおり、horizonかvertical、即ち縦か横です。

ちなみにデフォルトではQHBoxが採用されていて、指定しなければ横配置になります。

また、13行目の”self.upper.stateChanged.connect(self.uppercase)”というところも大切で、connectメソッドによって、”大文字”というチェックボックスにチェックが入っているとき、uppercaseにコネクトしてくれます。

uppercaseにコネクトされたあと、addWigetメソッドでself.upper_a, self.upper_bというWigetをaddしていますね。また、addWigetするときに、self.verticalが指定されています。

self.verticalにはQVBox、つまり縦のレイアウトが入っているので、チェックボックスが縦に並んでいるはずです。グループ化されていないので、複数のチェックボックスが選択することができますね。

またelse文では、チェックが外れた時に、removeWigetをすることによって、チェックボックスにチェックを入れるたびに、Wigetが追加されていくという現象を防いでいます。

アウトプットしてみよう

最後はアプリケーションらしく仕上げるために、選択したものをアウトプットしてみましょう。最終的なコードはこちらです。

import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sip

class MainWindow(QWidget):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        # 一つ目のチェックボックス
        self.upper = QCheckBox('大文字', self)
        self.upper.move(100, 30)
        self.upper.stateChanged.connect(self.uppercase)

        # 横のレイアウト
        self.horizon = QHBoxLayout()
        # 縦のレイアウト
        self.vertical = QVBoxLayout()

        # ボタンの追加
        self.button = QPushButton('excute', self)
        self.button.clicked.connect(self.output)

        self.horizon.addLayout(self.vertical)
        self.setLayout(self.horizon)

        self.setGeometry(300, 50, 400, 350)
        self.setWindowTitle('QCheckBox')

    def uppercase(self):
        if(self.upper.isChecked()):
            self.upper_a = QCheckBox('A', self)
            self.vertical.addWidget(self.upper_a)

            self.upper_b = QCheckBox('B', self)
            self.vertical.addWidget(self.upper_b)
        else:
            self.vertical.removeWidget(self.upper_a)
            self.vertical.removeWidget(self.upper_b)

    def output(self):
        outputs = []
        if(self.upper_a.isChecked()):
            outputs.append("A")
        if(self.upper_b.isChecked()):
            outputs.append("B")

        for output in outputs:
            print(output)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())


実行結果

execute後

A
B

こちらはPyQtはあまり関係ないので特筆すべきことはあまりないですが、QPushButtonでボタンを追加して、クリックしたらoutputメソッドにコネクトするようになっています。

まとめ

いかがでしたでしょうか。今回は、PyQtを使ってチェックボックスの中身をアウトプットしてみました。PyQtは他にもCSSを適用させることもできますし、メソッドや使い方は数多くあります。

細かい関数などは後々覚えるとして、レイアウトの概念や、関数の切り離し方、PyQtのなんとなくの使い方がわかってもらえたらOKですので、自分で試行錯誤しながら理解に努めてみてください!それでは!

この記事を書いた人

日向徹かこよすぎか

kaikaikai8217@gmail.com

目次