Python

最終更新日: 2023.04.15 (公開: 2023.04.04)

PythonのPyQtとは?GUIアプリ開発のメソッド・ウィジェットを解説

PythonのPyQtとは?GUIアプリ開発のメソッド・ウィジェットを解説

Pythonの「PyQt」は、クロスプラットフォーム対応のGUIアプリを作るためのライブラリです。GUIアプリの開発は難しいイメージがありますが、Pythonの「PyQt(パイキュート)」を使えば、高機能なGUIアプリが簡単に作れるようになります。

一方、PyQtは機能性が高いだけに、メソッドやウィジェットなどの種類が豊富です。そこで、「どう使えばいいかわからない」こと疑問に感じることもあるでしょう。今回は、PythonのGUIライブラリPyQtの使い方やテクニックについて、サンプルコード付きで解説します。

目次

Pythonの「PyQt(パイキュート)」とは

Pythonの「PyQt(パイキュート)」とは

Pythonの「PyQt(パイキュート)」とは、GUIアプリを開発するためのライブラリです。GUIとは「Graphical User Interface」のことでボタンやアイコンなど、グラフィックスを活用したプログラムを指します。GUIアプリはユーザーが簡単に使えるため、現在ではパソコンやスマホのアプリのほぼすべてが、GUIとなっています。

たとえば、インターネットを閲覧するときに使う「Google Chrome」や「Safari」、動画プラットフォームの「YouTube」などはすべてGUIアプリです。このようなGUIアプリを開発するために必要なのが、GUIライブラリです。GUIライブラリには、画像表示やユーザーのアクションに対応するために欠かせない、さまざまな機能が備わっています。

Pythonには、さまざまなGUIライブラリがありますが、その中でもPyQtは機能性やデザイン性が高いGUIアプリが作れるため、さまざまな場面で活用されています。なお、PyQtはバージョンアップが続けられており、現在では「PyQt5」や「PyQt6」が一般的です。なお、本記事では互換性を考慮して、すべてPyQt5でのソースコードを掲載しています。

PythonのPyQtを使うメリット

PythonのPyQtを使うメリット

PythonのPyQtを使うことで、以下3つのメリットが得られます。

  • GUIアプリ・プログラムが簡単に作れる
  • クロスプラットフォームに対応できる
  • 設計がモダンなのでデザイン面でも有利になる

GUIアプリ・プログラムが簡単に作れる

PyQtを利用すると、GUIアプリ・プログラムが簡単に作れるようになります。テキスト主体のCUI(Character User Interface)とは異なり、GUIアプリの開発には高度なスキルが要求されます。そのため、GUIプログラミングは「難しい」「気軽にできない」と思われがちです。たとえば、ウィンドウを表示するだけでも、複雑なソースコードを書かないといけません。

しかし、PyQtではごく短いコードを書くだけで、ウィンドウはもちろん画像やボタンなどを簡単に表示できます。高機能なGUIアプリを作る場合は、PyQt特有のメソッドやウィジェットへの理解を覚える必要はありますが、PyQtは全体的に簡潔で扱いやすい構造になっています。そのため、GUIプログラミングの初心者でも、気軽にチャレンジしやすいでしょう。

クロスプラットフォームに対応できる

PyQtを活用すると、「クロスプラットフォーム」対応のGUIアプリが作れます。クロスプラットフォームとは、簡単に言うと「さまざまなデバイス・環境で同じように動作できる」ことです。

たとえば、パソコンのOSには大きく分けて、WindowsとmacOSの2種類があります。それぞれまったく異なる思想・設計で構成されているため、片方のOSに向けて作られたソフトウェアは、もう一方のOSでは動作しません。したがって、複数のOSに対応したアプリを作るためには、それぞれのOSごとに異なるソースコードでプログラムを開発しないといけません。

しかし、クロスプラットフォームに対応したソフトウェアは、複数のOSで同じように動作します。PyQtでは、Windows・macOS・Linuxに対応したアプリが作れるため、さまざまなユーザーにアプリを提供したいときに便利です。

設計がモダンなのでデザイン面でも有利になる

Pythonで使えるGUIライブラリには、さまざまな種類があります。その中でも、PyQtは現在でも積極的な開発・アップデートが行われているライブラリなので、設計自体が「モダン」です。GUI画面のデザインの自由度が高いため、「見栄えがするアプリ」を作れます。

旧式のGUIライブラリを使っていると、「思うようにデザインできない」ことがあります。PyQtはボタンやテキストなどのデザインを変更したり、画像やアイコンを挿入したりすることが可能です。また、設計自体がモダンであることから、GUIに関する複雑な処理も簡潔に記載できることが魅力です。

PythonのPyQtを使うデメリット

PythonのPyQtを使うデメリット

PythonのPyQtを使うデメリットとして、以下の3つがあげられます。

  • 日本語で得られる情報が少ない
  • 複雑なアプリでは動作速度が遅い
  • ライセンス関連の条件が厳しい

日本語で得られる情報が少ない

PyQtは、公式ドキュメントの日本語版がないため、日本語で得られる情報量が少なめです。GUIプログラミングに慣れていない初心者にとっては、公式情報を得にくいことが気になるかもしれません。

しかし、PyQtの基本的なメソッドやウィジェットなどについては、公式以外のサイトやブログにて日本語で情報が公開されているため、問題解決の手段は比較的充実しているといえるでしょう。本記事でも、PyQtの基本的な使い方を解説します。

複雑なアプリでは動作速度が遅い

Python自体が「動作速度が遅い」言語として知られていますが、PyQtはグラフィックス処理を行うため、さらに動作速度が低下する傾向があります。GUIプログラミングの主流な手段として「C++」がありますが、PyQtのGUIアプリはC++で開発したものと比べて、動作速度は大幅に低い水準になります。動作速度が重要なアプリを開発する場合は、PyQtでも問題ないか事前に確認しておくほうが良いでしょう。

ライセンス関連の条件が厳しい

PyQtは、TkinterやPyGameなどのGUIライブラリと比べて、「ライセンス」の条件が厳しい点もデメリットです。

PyQtで開発したプログラムやアプリを販売する場合は、商用ライセンスを有償で取得しないといけません。また、PyQtは「GPLライセンス」であるため、非商用・商用を問わず、すべてのソースコードを公開する必要があります。

したがって、商用目的のアプリをPyQtで開発した場合は、収益面で不利になる可能性が高いです。すべてのソースコードを公開することで、競合開発者も同様のプログラムを容易に開発できるようになるからです。

そのため、商用目的でGUIプログラムやアプリを開発する場合は、TkinterやPyGameなど、ほかのGUIライブラリを利用するほうが良いでしょう。

PyQtの導入手順

PyQtの導入手順

PyQtは、Pythonに標準搭載されているライブラリではありません。そのため、Windows PCの場合は、以下の手順でPyQtをインストールする必要があります。まずは、「コマンドプロンプト」を開いて、以下のコマンドを入力してください。

py -m pip install PyQt5

このコマンドは、Pythonパッケージのインストールなどを行うユーティリティで、PyQt5をインストールするというものです。なお、前述したように2023年現在では「PyQt6」が最新バージョンですが、導入のしやすさや互換性の観点から「PyQt5」を使用します。

pyqt

続いて、「SIP」というツールも準備します。SIPは、C++で作成されたプログラムを、Pythonで利用するためのものです。PythonでPyQt5を使うためには、以下のコマンドでSIPをインストールする必要があります。

py -m pip install SIP

以上すべてのコマンドを入力すると、以下のような画面が表示されてインストールの完了となります。

pyqt

【基礎編】PyQtの基本的なウィジェットの使い方

【基礎編】PyQtの基本的なウィジェットの使い方

PyQtの基本的なウィジェットの使い方について、以下4つのポイントから解説します。

  • ウィンドウを生成する
  • ステータスバーを表示する
  • ステータスバーに時計を表示する
  • メニューバーを表示する

ウィンドウを生成する

GUIプログラミングの第一歩は「ウィンドウの生成」です。PyQtでは、QMainWindowクラスの「show()関数」を呼び出すとウィンドウが表示されます。ただし、ウィンドウのさまざまな機能を便利に使うために、「QMainWindowクラス」を継承したクラスを作成することが一般的です。詳細は以下のサンプルコードのとおりです。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QMainWindowクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):

    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)

    # ウィンドウを表示する
    self.show()

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())

//実行結果

上記のプログラムでは、QMainWindowクラスを継承した「Programクラス」を作成しています。コンストラクタでQMainWindowクラスを初期化してから、show()を呼び出していることがポイントです。なお、setWindowTitle()でウィンドウタイトルを、setGeometry()でウィンドウサイズを設定できます。

「from PyQt5.QtCore import *」と「from PyQt5.QtWidgets import*」は、それぞれ「PyQt5.QtCore」と「PyQt5.QtWidgets」の内部にあるすべてのモジュールをimportするということです。初心者が学習するときは、ワイルドカードを使うほうがわかりやすいためおすすめです。

ステータスバーを表示する

簡易的な情報を表示するための「ステータスバー」は、「self.statusBar().showMessage()メソッド」で表示できます。なお、QMainWindowクラスを継承していなければ、この機能は使えないので注意が必要です。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):

    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)

    # ウィンドウを表示する
    self.show()
    
    # ステータスバーを表示する
    self.statusBar().showMessage("ステータスバーの情報")

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())

//実行結果

pyqt

上記のように、メインウィンドウの下部にステータスバーが表示されます。このステータスバーに、プログラムの進行状況を表示するようにすると、よりユーザーフレンドリーなGUIアプリが作れるでしょう。

ステータスバーに時計を表示する

ステータスバーに簡易的な時計を表示したい場合は、QTimerオブジェクトを生成します。QTimerオブジェクトの「timeout.connect()関数」の引数に、現在日時を表示するためのメソッドを指定すればOKです。詳細は以下のサンプルコードのとおりです。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「sipモジュール」をインポートする
import sip

# 「datetimeモジュール」をインポートする
import datetime

# 「localeモジュール」をインポートする
import locale

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()
    
    # システムロケールを設定する
    # setlocale()を呼び出さなければ、PyQtで日本語を表示できない
    locale.setlocale(locale.LC_ALL, "")

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):

    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)

    # ウィンドウを表示する
    self.show()

    # QTimerを初期化する
    timer = QTimer(self)

    # timeoutシグナルに「getDateTime()メソッド」をスロットとして指定する
    timer.timeout.connect(self.getDateTime)

    # タイマーの動作を開始する
    timer.start()

  # getDateTime()メソッド|ステータスバーに現在日時を表示する
  def getDateTime(self):
    # 現在の日時を取得する
    time = datetime.datetime.today()

    # 取得した日時をフォーマット済み文字列形式に変換する
    string = time.strftime(u"%Y年%m月%d日 %H時%M分%S秒")

    # ステータスバーに現在日時を表示する
    self.statusBar().showMessage(f"現在時刻:{string}")

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果

pyqt

現在日時を表示するための「getDateTime()メソッド」の内部では、datetime.datetime.today()で取得した日時を文字列に変換し、statusBar().showMessage()の引数に引き渡しています。

なお、Programクラスのコンストラクタで「locale.setlocale()」という関数を呼び出していますが、これはプログラム内で日本語を表示するためのものです。この工程を挟んでおかなければ、文字化けやエラーが発生してしまうので注意が必要になることを留意します。

また、PyQtでは「シグナル」と「スロット」という概念が重要です。シグナルは、プログラム内でアクションや変化が起きたときに発生し、スロットでその対応を行います。上記のサンプルプログラムの場合は、タイマーのタイムアウト時に「timer.timeoutシグナル」が発生し、「getDateTime()メソッド」をスロットとしています。こうすることで、自動的にステータスバーの内容が変更されるようになるので便利です。

メニューバーを表示する

GUIプログラムでは、ユーザーがさまざまな処理や操作を行うために、メニューバーの存在が欠かせません。メニューバーは、まずメニューバーオブジェクトを「menuBar()」で作成し、その「addMenu()」を呼び出してメニュー項目を追加します。詳細は以下のサンプルコードのとおりです。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # メニューバーを表示する
    self.setMenuBar()

    # ウィンドウを表示する
    self.show()

  # setMenuBar()メソッド|メニューバーを生成する
  def setMenuBar(self):

    # メニューバーを生成する
    menubar = self.menuBar()

    # メニューバーに「ファイル」項目を追加する
    fileMenu = menubar.addMenu("ファイル")

    # 「終了」アクションを作成する
    exitAction = QAction("終了", self)
    
    # 「終了」アクションのショートカットを設定する
    exitAction.setShortcut("Ctrl+Q")

    # 「終了」アクションのステータスバーのメッセージを設定する
    exitAction.setStatusTip("プログラムを終了します")

    # 「終了」アクションとqApp.quit()メソッドを関連付ける
    exitAction.triggered.connect(qApp.quit)

    # メニューバーの「ファイル」項目に「終了」アクションを追加する
    fileMenu.addAction(exitAction)

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期画面

pyqt

「終了」アクションにマウスカーソルを合わせたとき

pyqt

上記のサンプルプログラムでは、メニュー項目の「アクション」も設定しています。まずQActionオブジェクトを作成し、その「triggered.connect()」にスロットを設定しましょう。ショートカットは「setShortcut()」、ステータスバーのメッセージは「setStatusTip()」で設定可能です。そのうえで、addAction()の引数にアクションを指定すれば、便利なメニューバーを作成できます。

ウィジェットの種類

PythonのPyQtを活用するためには、GUI画面の部品である「ウィジェット」を使いこなすことが重要です。今回は、PyQtの主要ウィジェット13種類について解説します。

  • QLabel(ラベル)
  • QPushButton(プッシュボタン)
  • QLineEdit(ラインエディット)
  • QTextEdit(テキストエディット)
  • QToolButton(ツールボタン)
  • QRadioButton(ラジオボタン)
  • QCheckBox(チェックボックス)
  • QPixmap(ピクセルマップ)
  • QSlider(スライダー)
  • QDial(ダイアル)
  • QProgressBar(プログレスバー)
  • QCalendarWidget(カレンダーウィジェット)
  • QDateTimeEdit(デートタイムエディット)

QLabel(ラベル)

「QLabel(ラベル)」は、GUI画面にラベルを表示するためのウィジェットです。QLabelオブジェクトを生成し、setText()でテキストの文字列を設定できます。さらに、setFont()・setFrameStyle()・setLineWidth()などで、詳細の設定が可能です。QLabelウィジェットの使い方について、以下のサンプルコードで確認しましょう。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ラベルを生成する
    label = QLabel(self)

    # ラベルに表示するテキストを設定する
    label.setText("サンプルテキスト")

    # テキストのフォントを設定する
    label.setFont(QtGui.QFont("メイリオ", 30, QtGui.QFont.Bold))
    
    # 枠線のスタイルを設定する
    label.setFrameStyle(QFrame.Box | QFrame.Raised)

    # 枠線の太さを設定する
    label.setLineWidth(5)

    # ラベルのサイズをテキストに合わせる
    label.adjustSize()

    # 枠の中心にテキストを表示するようにする
    label.setAlignment(Qt.AlignCenter)

    # ラベルの位置をX座標50・Y座標120に設定する
    label.move(50, 120)

    # ウィンドウを表示する
    self.show()

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果

pyqt

上記のサンプルプログラムでは、フォントやスタイルを指定したラベルを作成しています。setFrameStyle()で「QFrame.Raised」を指定しているため、立体的な印象になっています。PyQtは、こうしたデザインも簡単にできることが魅力です。なお、後述する「レイアウト」を使用しない場合は、ウィジェットのサイズを調整する必要があります。adjustSize()を呼び出すことで、内容に合わせたサイズへの自動調整となります。

QPushButton(プッシュボタン)

「QPushButton(プッシュボタン)」ウィジェットは、クリックできる通常のボタンです。QPushButtonオブジェクトを生成すると、プッシュボタンを表示できます。setDefault()でデフォルトの状態、setFlat()でフラットボタンかどうか、setCheckable()でトグルボタンかどうかを設定可能です。setChecked()を呼び出せば、トグルボタンの初期状態を指定できます。詳細は以下のサンプルコードのとおりです。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # 3つのボタンを生成する
    button_1 = QPushButton("ボタン1", self)
    button_2 = QPushButton("ボタン2", self)
    button_3 = QPushButton("ボタン3", self)

    # 「ボタン1」はデフォルト状態で押された状態にする
    # setDefault()を呼び出さない場合は「False」となる
    button_1.setDefault(True)
    
    # 「ボタン2」をフラットボタンにする
    button_2.setFlat(True)
    
    # 「ボタン3」をトグルボタンにする
    # setChecked()で初期状態を設定する
    button_3.setCheckable(True)
    button_3.setChecked(False)

    # 各ボタンの位置とサイズを設定する
    button_1.setGeometry(200, 100, 200, 50)
    button_2.setGeometry(200, 200, 200, 50)
    button_3.setGeometry(200, 300, 200, 50)

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())

//実行結果
初期状態

pyqt

トグルボタンを押したとき

pyqt

ボタンが押されたときにアクションを起こしたいときは、ボタンの「clicked.connect()メソッド」に、アクションの内容を記載したメソッドを指定します。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # ボタンを生成する
    button = QPushButton("終了", self)

    # 各ボタンの位置とサイズを設定する
    button.setGeometry(200, 100, 200, 50)
    
    # clickedシグナルに「qApp.quit()メソッド」をスロットとして指定する
    # ボタンを押すとプログラムが終了する
    button.clicked.connect(qApp.quit)

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())

//実行結果

pyqt

QLineEdit(ラインエディット)

1行だけテキストを入力できる項目を追加するときは、「QLineEdit(ラインエディット)」ウィジェットを使用しましょう。QLineEditオブジェクトを生成するだけで、ユーザーが1行だけ入力できるテキストボックスが表示されます。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):
    
    # テキストボックスを生成する
    self.line = QLineEdit("テキストを入力してください", self)
    
    # テキストボックスの表示位置とサイズを設定する
    self.line.setGeometry(120, 150, 350, 50)

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期画面

pyqt

テキスト入力後

pyqt

なお、QLineEditオブジェクトのsetEchoMode()メソッドの引数に「QLineEdit.EchoMode.Password」を指定すると、パスワードモードになり、入力した文字列が隠蔽されます。また、「textChangedシグナル」に任意のメソッドをスロットとして指定すると、テキスト変更時にそのメソッドが自動的に呼び出されます。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):
    
    # ラベルを生成する
    label = QLabel("パスワード", self, font = QtGui.QFont("メイリオ", 15))
    
    # ラベルの表示位置を設定する
    label.move(120, 80)

    # ラベルのサイズをテキストに合わせる
    label.adjustSize()

    # テキストボックスを生成する
    self.line = QLineEdit(self)
    
    # テキストボックスを生成する
    self.line.setEchoMode(QLineEdit.EchoMode.Password)
    
    # テキストボックスの表示位置とサイズを設定する
    self.line.setGeometry(120, 150, 350, 50)
    
    # textChangedシグナルに「getNewText()メソッド」をスロットとして指定する
    # テキストが変更されたときはgetNewText()が自動的に呼び出される
    self.line.textChanged.connect(self.getNewText)
    
  # getNewText()メソッド|新しいテキストを表示する
  def getNewText(self):

    # text()メソッドを呼び出すことで、テキストボックスの文字列が取得できる
    print(f"入力されたパスワード:{self.line.text()}")

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
GUI画面

pyqt

コンソール画面

pyqt

上記のサンプルプログラムでは、ユーザーがテキストボックスの内容を変更するたびに、その内容がコンソール画面に表示されます。textChangedシグナルに指定したgetNewText()メソッド内部では、text()を呼び出してテキストボックスの文字列を取得していることがポイントです。

QTextEdit(テキストエディット)

改行できるテキストボックスを設置したい場合は、「QTextEdit(テキストエディット)」を使用しましょう。QTextEditオブジェクトを生成すると、ユーザーが自由に入力・編集できるテキストボックスが表示されます。なお、「font引数」で好みのフォントを指定することで、見やすいテキストボックスになります。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):
    
    # テキストボックスを生成する
    self.text = QTextEdit("テキストを入力してください", self, font = QtGui.QFont("メイリオ", 10))
    
    # テキストボックスの表示位置とサイズを設定する
    self.text.setGeometry(10, 10, 620, 460)

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期状態

pyqt

テキスト入力時

pyqt

テキストの内容を取得したい場合は、QTextEditオブジェクトの「toPlainText()メソッド」を呼び出すことで、ユーザーが入力した文字列を取得できます。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # フォント情報を生成する
    self.font = QtGui.QFont("メイリオ", 10)
    
    # テキストボックスを生成する
    self.text = QTextEdit("テキストを入力してください", self, font = self.font)
    
    # テキストボックスの表示位置とサイズを設定する
    self.text.setGeometry(10, 10, 620, 400)
    
    # ボタンを生成する
    button = QPushButton("入力完了", self, font = self.font)

    # ボタンの位置を設定する
    button.move(250, 430)
    
    # clickedシグナルに「getText()メソッド」をスロットとして指定する
    # 「入力完了」ボタンをクリックしたときに、このメソッドが自動的に呼び出される
    button.clicked.connect(self.getText)
    
  # getText()メソッド|新規テキストを画面に表示する
  def getText(self):
    print(self.text.toPlainText())

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
GUI画面

pyqt

コンソール画面

pyqt

上記のサンプルプログラムでは、ユーザーが「入力完了」ボタンを押すと、テキストボックスに入力したテキストがコンソール画面に表示されます。このように、ボタンクリックでアクションを起こすケースが多いので、一連の流れに慣れておきましょう。

QToolButton(ツールボタン)

先ほど紹介したQPushButtonは横長のボタンなので、アイコンの表示には不向きです。ツールバーに表示するような正方形のボタンを使用したい場合は、「QToolButton(ツールボタン)」を使用しましょう。QToolButtonオブジェクトを生成し、setIcon()メソッドに「QIconオブジェクト」を引き渡すことで、ボタンにアイコンを表示できます。詳細は以下のサンプルコードのとおりです。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui
from PyQt5.QtGui import QIcon

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # ボタンを生成する
    button = QToolButton(self)
    
    # ボタンのアイコンを設定する
    button.setIcon(QIcon(self.style().standardPixmap(QStyle.SP_DialogOpenButton)))

    # ボタンのテキストを設定する
    button.setText("終了");
    
    # テキストの表示形式を設定する
    # 「ToolButtonTextBesideIcon」はアイコンの横
    # 「ToolButtonTextUnderIcon」はアイコンの下
    button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon);
    
    # ボタンのサイズを合わせる
    button.adjustSize()
    
    # clickedシグナルに「qApp.quit()メソッド」をスロットとして指定する
    # ボタンを押すとプログラムが終了する
    button.clicked.connect(qApp.quit)

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())

//実行結果

pyqt

 

上記のサンプルプログラムでは、アイコンとテキストをボタン内に併記しています。QIconオブジェクトの生成時は、style().standardPixmap()メソッドを呼び出し、アイコンの種類を選ぶ必要があるでしょう。今回の例では、ダイアログを開くアイコンである「QStyle.SP_DialogOpenButton」です。

また、アイコンとテキストを併記するときは、setToolButtonStyle()メソッドで表示形式を指定できます。テキストの表示形式は、以下の5種類から選びます。

テキストの表示形式 概要
ToolButtonIconOnly アイコンのみ表示する
ToolButtonTextOnly テキストのみ表示する
ToolButtonTextBesideIcon アイコンの横にテキストを表示する
ToolButtonTextUnderIcon アイコンの下にテキストを表示する
ToolButtonFollowStyle スタイルに従って表示する

QRadioButton(ラジオボタン)

複数の選択肢から1つだけ選べるようにしたい場合は、「QRadioButton(ラジオボタン)」ウィジェットを使用します。QRadioButtonオブジェクトを生成することで、ラジオボタンの原型が整います。詳細を以下のサンプルコードで確認しましょう。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # 3つのラジオボタンを生成する
    radio_button_1 = QRadioButton("ラジオボタン1", self)
    radio_button_2 = QRadioButton("ラジオボタン2", self)
    radio_button_3 = QRadioButton("ラジオボタン3", self)

    # 「ラジオボタン1」はデフォルト状態で押された状態にする
    # setChecked()を呼び出さない場合は「False」となる
    radio_button_1.setChecked(True)

    # 各ラジオボタンのサイズをテキストに合わせる
    radio_button_1.adjustSize()
    radio_button_2.adjustSize()
    radio_button_3.adjustSize()

    # 各ラジオボタンの位置を設定する
    radio_button_1.move(200, 100)
    radio_button_2.move(200, 200)
    radio_button_3.move(200, 300)

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期状態

pyqt

ボタンクリック時

pyqt

以上のように、1つしか選べないボタンが表示されます。ただし、クリックしたときにアクションを起こすなど、ラジオボタンとして正しく機能させるためには、以下のように「QButtonGroupオブジェクト」にラジオボタンを追加する必要があります。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # 3つのラジオボタンを生成する
    radio_button_1 = QRadioButton("ラジオボタン1", self)
    radio_button_2 = QRadioButton("ラジオボタン2", self)
    radio_button_3 = QRadioButton("ラジオボタン3", self)

    # 各ラジオボタンのサイズをテキストに合わせる
    radio_button_1.adjustSize()
    radio_button_2.adjustSize()
    radio_button_3.adjustSize()

    # 各ラジオボタンの位置を設定する
    radio_button_1.move(200, 100)
    radio_button_2.move(200, 200)
    radio_button_3.move(200, 300)

    # ボタングループを生成する
    self.button_group = QButtonGroup()

    # 各ラジオボタンをボタングループに追加する
    self.button_group.addButton(radio_button_1)
    self.button_group.addButton(radio_button_2)
    self.button_group.addButton(radio_button_3)
    
    # buttonClickedシグナルに「getClickedButton()メソッド」をスロットとして指定する
    # スロットの引数には自動的に押されたボタンが引き渡される
    self.button_group.buttonClicked.connect(self.getClickedButton)
    
  # getClickedButton()メソッド|クリックされたボタンを取得する
  def getClickedButton(self, button):

    # 「button.text()メソッド」を呼び出すことで、ボタンのテキストを取得できる
    print(f"「{button.text()}」がクリックされました")

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期状態

pyqt

ボタンクリック時

pyqt

QButtonGroupオブジェクトを生成したあとで、addButton()メソッドの引数に各ラジオボタンを指定することで、すべてのボタンがグループ化されます。そのオブジェクトのbuttonClicked.connect()にスロットを設定することで、どのボタンがクリックされたときでも同じメソッドが呼び出されるようになります。

QCheckBox(チェックボックス)

複数の選択肢を自由に選べるチェックボックスは、「QCheckBoxウィジェット」で作成できます。ただし、QRadioButtonとは異なりQButtonGroupを使用しません。QButtonGroupを使用した場合は複数チェックができず、チェックボックスとしての機能を果たさなくなるので注意が必要です。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):
    
    # チェックボックスを生成する
    check_box_1 = QCheckBox(f"チェックボックス1", self)
    check_box_2 = QCheckBox(f"チェックボックス2", self)
    check_box_3 = QCheckBox(f"チェックボックス3", self)
    
    # 各チェックボックスのサイズをテキストに合わせる
    check_box_1.adjustSize()
    check_box_2.adjustSize()
    check_box_3.adjustSize()

    # 各チェックボックスの位置を設定する
    check_box_1.move(200, 100)
    check_box_2.move(200, 200)
    check_box_3.move(200, 300)

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期状態

pyqt

チェックボックスのクリック時

pyqt

チェックボックスの「toggled.connect()」シグナルに、任意のスロットを指定すればOKです。ただし、通常の方法ではチェックボックスごとに、スロットを作成しないといけないのが不便なところ。そこで以下のサンプルコードのように、「クロージャー(関数内関数)」を使用するのがおすすめです。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # 3つのチェックボックス・オブジェクトを格納するためのリスト
    check_boxes = [None] * 3

    # 3つのチェックボックスを生成する
    for i in range(3):

      # チェックボックスを生成する
      check_boxes[i] = QCheckBox(f"チェックボックス{i + 1}", self)

      # チェックボックスのサイズをテキストに合わせる
      check_boxes[i].adjustSize()

      # チェックボックスの位置を設定する
      check_boxes[i].move(200, 100 * (i + 1))
    
      # toggledシグナルに「checkBoxClicked()メソッド」をスロットとして指定する
      # スロットの引数にはチェックの状態が引き渡される
      check_boxes[i].toggled.connect(self.checkBoxClicked(i))
      
  # checkBoxClicked()メソッド|チェックボックスのクリック時のアクション
  # 引数としてチェックボックス番号を受ける
  def checkBoxClicked(self, i):

    # スロットをネストする「クロージャー(関数内関数)」として定義する
    # 引数としてボックスのチェック状態を受ける
    def inner(checked):
      print(f"「チェックボックス{str(i + 1)}」のチェック状態は「{checked}」です")

    # 間接的にcheckBoxClicked()メソッドを呼び出す
    return inner

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())

//実行結果
初期画面

pyqt

チェックボックスのクリック時

pyqt

コンソール画面

pyqt

関数の中にある関数を「クロージャー(関数内関数)」と呼びます。クロージャーの特徴は、外側の関数の変数を記憶している点です。上記のサンプルプログラムの場合は、inner()内部でcheckBoxClicked()の引数である「i」が記憶されています。そのため、toggled.connect()でスロットを指定するときに指定したインデックス「i」で、どのチェックボックスがクリックされたか判定することが可能です。

このように、複数のチェックボックスを配列で管理したり、クロージャーを活用したりすると、ソースコードを大幅に簡潔化できます。

QPixmap(ピクセルマップ)

ウィンドウに画像を表示したいときは、「QPixmap(ピクセルマップ)」ウィジェットを活用しましょう。QPixmapオブジェクトの生成時に画像ファイルを指定することで、画像データを表示する準備が自動的に整います。あとはQLabelオブジェクトを生成し、setPixmap()メソッドで画像をはめ込めばOKです。今回は、以下の画像を「Flower.jpg」という名称でメインモジュールと同じディレクトリに保存し、次のサンプルコードを実行しましょう。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui
from PyQt5.QtGui import QPixmap

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # ラベルを生成する
    # 画像はラベルに埋め込む
    label = QLabel(self)

    # QPixmapオブジェクトで画像を読み込む
    pixmap = QPixmap("Flower.jpg")

    # 画像の横幅をウィンドウサイズに合わせる
    pixmap = pixmap.scaledToWidth(640)
    
    # ラベルに画像を挿入する
    label.setPixmap(pixmap)

    # ラベルのサイズを画像に合わせる
    label.adjustSize()

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果

pyqt

このように、PyQtでは非常に簡単な手順で画像やイラストを表示できます。なお、「style().standardPixmap()メソッド」を活用すると、標準で搭載されているアイコン画像を使うことも可能です。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui
from PyQt5.QtGui import QPixmap

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

# コンストラクタ
def __init__(self):

# QWidgetクラスを初期化する
super().__init__()

# PyQtのウィンドウを生成する
self.createWindow()

# createWindow()メソッド|PyQtのウィンドウを生成する
def createWindow(self):

# ウィンドウのタイトルを設定する
self.setWindowTitle("PyQtサンプルプログラム")

# ウィンドウのサイズを設定する
self.setGeometry(0, 0, 640, 480)

# ステータスバーを表示する
self.statusBar()

# ウィジェットを生成する
self.initWidget()

# ウィンドウを表示する
self.show()

# initWidget()メソッド|ウィジェットを生成する
def initWidget(self):

# ラベルを生成する
# アイコンはラベルに埋め込む
label_computer = QLabel(self)
label_drive = QLabel(self)
label_open = QLabel(self)
label_apply = QLabel(self)

# ラベルの位置とサイズを設定する
label_computer.setGeometry(0, 0, 100, 100)
label_drive.setGeometry(120, 0, 100, 100)
label_open.setGeometry(240, 0, 100, 100)
label_apply.setGeometry(360, 0, 100, 100)

# ラベルにアイコン挿入する
label_computer.setPixmap(self.style().standardPixmap(QStyle.SP_ComputerIcon))
label_drive.setPixmap(self.style().standardPixmap(QStyle.SP_DriveHDIcon))
label_open.setPixmap(self.style().standardPixmap(QStyle.SP_DirOpenIcon))
label_apply.setPixmap(self.style().standardPixmap(QStyle.SP_DialogApplyButton))

# アイコンのサイズを画像に合わせる
label_computer.setScaledContents(True);
label_drive.setScaledContents(True);
label_open.setScaledContents(True);
label_apply.setScaledContents(True);

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

# PyQtを初期化する
app = QApplication(sys.argv)

# Programクラスのインスタンスを生成する
program = Program()

# プログラムを終了する
sys.exit(app.exec_())

//実行結果

pyqt

style().standardPixmap()メソッドに、使用するアイコンを指定することで、ラベルにアイコンを表示できます。代表的な標準アイコンは以下のとおりです。

SP_TitleBarMenuButton タイトルバーのメニューボタン
SP_TitleBarMinButton タイトルバーの最小化ボタン
SP_TitleBarMaxButton タイトルバーの最大化ボタン
SP_TitleBarCloseButton タイトルバーの閉じるボタン
SP_TitleBarNormalButton タイトルバーの通常ボタン
SP_TitleBarShadeButton タイトルバーの隠すボタン
SP_TitleBarUnshadeButton タイトルバーの表示ボタン
SP_TitleBarContextHelpButton タイトルバーのヘルプボタン
SP_MessageBoxInformation インフォメーション
SP_MessageBoxWarning 警告マーク
SP_MessageBoxCritical 致命的エラー
SP_MessageBoxQuestion 質問マーク
SP_DesktopIcon デスクトップ
SP_TrashIcon ゴミ箱
SP_ComputerIcon コンピューター
SP_DirOpenIcon 開いているディレクトリ
SP_DirClosedIcon 閉じているディレクトリ
SP_DirLinkIcon リンクディレクトリ
SP_FileDialogStart ファイルダイアログの開始
SP_FileDialogEnd ファイルダイアログの終了
SP_FileDialogToParent ファイルダイアログの親ディレクトリ

QSlider(スライダー)

左右に動かすことで値を変更できるスライダーは、「QSliderウィジェット」で表示できます。QSliderオブジェクトを生成し、setMinimum()・setMaximum()・setValue()などのメソッドを呼び出すことで、スライダーの仕様を設定できます。valueChanged.connect()メソッドで、値が変更されたときのスロットを設定可能です。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui
from PyQt5.QtGui import QPixmap

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # スライダーの初期値を設定する
    initial_value = 100
    
    # スライダーの個数を設定する
    self.num_sliders = 5

    # ウィジェットを生成する
    widget = QWidget()

    # ラベルを生成する
    self.labels = [QLabel() for x in range(self.num_sliders)]
    
    # ラベルの初期値を設定する
    for x in self.labels:
      x.setText(str(initial_value))

    # スライダーを生成する
    self.sliders = [QSlider(Qt.Orientation.Horizontal) for x in range(self.num_sliders)]
    
    # 各スライダーの仕様を設定する
    for each_slider in self.sliders:

      # 最小値
      each_slider.setMinimum(10)

      # 最大値
      each_slider.setMaximum(1000)

      # 初期値
      each_slider.setValue(initial_value)
      
      # valueChangedシグナルに「getNewValues()メソッド」をスロットとして指定する
      each_slider.valueChanged.connect(self.getNewValues)
    
    # GridLayoutオブジェクトを生成する
    layout = QGridLayout()

    # ラベルとスライダーをレイアウトに追加する
    for i in range(self.num_sliders):
      layout.addWidget(self.labels[i], i, 0)
      layout.addWidget(self.sliders[i], i, 1)
    
    # レイアウト適用済みのウィジェットをメインウィンドウに追加する
    widget.setLayout(layout)
    self.setCentralWidget(widget)
    
  # getNewValues()メソッド|スライダー変更時に新しい値を取得する
  def getNewValues(self):

    # 各スライダーの値をラベルに反映させる
    for i in range(self.num_sliders):
      # スライダーの「value()メソッド」で値を取得できる
      self.labels[i].setText(str(self.sliders[i].value()))

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期状態

pyqt

スライダー変更時

pyqt

上記のように、スライダーのダイヤルを動かすことで、自由に値を変更できます。etNewValues()メソッドの内部では、スライダーの値をラベルに反映させていることがポイントです。なお、今回はグリッドと値を並べて表示するために、QGridLayoutオブジェクトというレイアウト機能を使用しています。レイアウトの詳細については後述します。

QDial(ダイアル)

「QDial(ダイアル)ウィジェット」は、回転させることで値を変更するためのものです。QDialオブジェクトを生成し、setValue()関数で初期値を設定できます。

valueChanged.connect()の引数で、値が変更されたときのスロットを指定可能です。QDialの使い方を以下のサンプルコードで確認しましょう。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# 「timeモジュール」をインポートする
import time

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):
    
    # ダイアルを生成する
    dial = QDial(self)
    
    # ダイアルの最小値と最大値を設定する
    dial.setRange(-100, 100)
    
    # ダイアルの初期値を設定する
    dial.setValue(0)
    
    # ダイアルのvalueChangedシグナルに「getValue()メソッド」をスロットとして指定する
    dial.valueChanged.connect(self.getValue)

    # ダイアルウィジェットの位置とサイズを設定する
    dial.setGeometry(100, 100, 300, 300)
    
    # ラベルを生成する
    self.label = QLabel("±000", self)
    
    # テキストのフォントを設定する
    self.label.setFont(QtGui.QFont("メイリオ", 30, QtGui.QFont.Bold))
    
    # ラベルウィジェットの位置とサイズを設定する
    self.label.setGeometry(400, 300, 200, 100)
    
    # getValue()メソッド|ダイアルの値をラベルに表示する
  def getValue(self, value):

    # 変更後の「value」の値をラベルに設定する
    self.label.setText(str(value))

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期画面

pyqt

ダイアル変更後

pyqt

QProgressBar(プログレスバー)

データの読み込みや処理を行うときなどに、その進行状況を表示したいことがあるでしょう。「QProgressBar(プログレスバー)」を使用すると、プロセスの進行状況を可視化できます。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui
from PyQt5.QtGui import QPixmap

# 「sipモジュール」をインポートする
import sip

# 「timeモジュール」をインポートする
import time

# 「threadingモジュール」をインポートする
import threading

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # ウィジェットを生成する
    widget = QWidget()

    # プログレスバーを生成する
    self.bar = QProgressBar()

    # 初期値を「50」に設定する
    self.bar.setValue(50)
    
    # GridLayoutオブジェクトを生成する
    layout = QGridLayout()

    # プログレスバーをレイアウトに追加する
    layout.addWidget(self.bar)
    
    # レイアウト適用済みのウィジェットをメインウィンドウに追加する
    widget.setLayout(layout)
    self.setCentralWidget(widget)

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果

pyqt

なお、プログレスバーは以下のように自由に進行できます。今回は、メインウィンドウの「ステータスバー」に、プログレスバーを埋め込むサンプルプログラムをご紹介しましょう。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui
from PyQt5.QtGui import QPixmap

# 「sipモジュール」をインポートする
import sip

# 「timeモジュール」をインポートする
import time

# 「threadingモジュール」をインポートする
import threading

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()

    # プログレスバーを進行させる
    self.progress()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # ウィジェットを生成する
    widget = QWidget()

    # プログレスバーを生成する
    self.bar = QProgressBar()
    
    # メインウィンドウのステータスバーに、プログレスバーを埋め込む
    self.statusBar().addWidget(self.bar);

    # 初期値を「0」に設定する
    self.bar.setValue(0)

  # progress()メソッド|プログレスバーを進行させる
  def progress(self):

    # プログレスバーの進行度
    value = 0

    # プログレスバーが100になるまで無限ループを回す
    while True:
      # 無限forループなどを回していると、GUI画面が固まってしまう。
      # そこで、毎ループ「QApplication.processEvents()メソッド」を呼び出すことにより、
      # 未処理のイベントを済ませてから、forループの処理に戻ることができる。
      # 引数に「QEventLoop.ExcludeUserInputEvents」を指定すると、
      # ウィジェットなどに対するユーザーの入力を防げるため、想定外の動作を防げて安全
      QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)

      # プログレスバーの値を更新する
      self.bar.setValue(value)

      # プログレスバーを1だけ進める
      # 値が100を超えた場合は処理を終了する
      value += 1
      if(value > 100):
        break

      # 0.05秒だけ待機する
      time.sleep(0.05)
      
    # 1秒待機する
    time.sleep(1)

    # 処理の完了後は、ステータスバーからプログレスバーを削除して、完了メッセージを表示する
    self.statusBar().removeWidget(self.bar)
    self.statusBar().showMessage("処理が完了しました!")

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期状態

pyqt

処理進行中

pyqt

処理完了後

pyqt

無限ループを回し、その中でプログレスバーのsetValue()を呼び出し、値を増やしていることがポイントです。time.sleep()を活用し、1ループあたり0.05秒ずつ待つことで、プログレスバーが徐々に増えます。

また、「QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)」と記載することで、forループ中にGUI画面が固まるのを防ぐことが可能です。この処理を挟まなければ、無限ループが終わるまで、ユーザーは画面を一切操作できないようになってしまいます。

マルチスレッドを使うのもひとつの方法ですが、マルチスレッドは扱いが非常に難しく、想定外のバグやエラーの原因になりやすいことが難点です。QApplication.processEvents()を呼び出すことで、GUI画面のフリーズを簡単に防げるのでおすすめです。

QCalendarWidget(カレンダーウィジェット)

「QCalendarWidget(カレンダーウィジェット)」を使えば、以下のようにGUI画面にカレンダーを表示させることもできます。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui
from PyQt5.QtGui import QPixmap

# 「sipモジュール」をインポートする
import sip

# 「timeモジュール」をインポートする
import time

# 「threadingモジュール」をインポートする
import threading

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # カレンダーを生成する
    calendar = QCalendarWidget(self)
    
    # カレンダーの位置を設定する
    calendar.move(50, 50)

    # カレンダーのサイズを調整する
    calendar.adjustSize()

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果

pyqt

QDateTimeEdit(デートタイムエディット)

「QDateTimeEdit(デートタイムエディット)」を使うと、より詳細な情報を表示できるうえに、値を変更できるカレンダーを表示できます。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui
from PyQt5.QtGui import QPixmap

# 「sipモジュール」をインポートする
import sip

# 「timeモジュール」をインポートする
import time

# 「threadingモジュール」をインポートする
import threading

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # カレンダーを生成する
    self.calendar = QDateTimeEdit(self)

    # 現在日時をカレンダーのデフォルトとする
    self.calendar.setDateTime(QDateTime.currentDateTime())

    # クリック時にカレンダーを表示する
    self.calendar.setCalendarPopup(True)
    
    # カレンダーの位置とサイズを設定する
    self.calendar.setGeometry(100, 50, 200, 50)
    
    # 日時が変更されたときは「calendar_changed()関数」を呼び出す
    self.calendar.dateTimeChanged.connect(self.calendar_changed)
    
  # calendar_changed()メソッド|カレンダー変更時のメソッド
  def calendar_changed(self):

    # dateTime().toString()で変更後の日時を取得可能
    print(self.calendar.dateTime().toString("yyyy/MM/dd HH:mm:ss"))

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期画面

pyqt

日時の変更時

pyqt

コンソール画面

pyqt

レイアウトの種類

レイアウトの種類

GUI画面を自由に作り出すためには、「レイアウト」機能を使うことも重要です。PyQtでは、以下の4種類のレイアウトが使えます。

  • QHBoxLayout
  • QVBoxLayout
  • QGridLayout
  • QFormLayout

QHBoxLayout

「QHBoxLayout」は、ウィジェットを横に並べるためのレイアウトです。QHBoxLayoutオブジェクトを生成してから、addWidget()関数でウィジェットを指定すると、指定した順番どおりにウィジェットが横に並びます。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # ウィジェットを生成する
    # メインウィンドウにレイアウトを直接指定するとエラーになるため、
    # まずWidgetオブジェクトに各要素を入れて、レイアウトを設定してから、
    # Widgetオブジェクトをメインウィンドウに配置する
    widget = QWidget()
    
    # QHBoxLayoutオブジェクトを生成する
    layout = QHBoxLayout()

    # 4つのラベルを生成する
    label_1 = QLabel("テキスト1", self)
    label_2 = QLabel("テキスト2", self)
    label_3 = QLabel("テキスト3", self)
    label_4 = QLabel("テキスト4", self)

    # QHBoxLayoutオブジェクトに4つのラベルを追加する
    layout.addWidget(label_1)
    layout.addWidget(label_2)
    layout.addWidget(label_3)
    layout.addWidget(label_4)

    # Widgetオブジェクトにレイアウトを反映させる
    widget.setLayout(layout)

    # ウィジェットにレイアウトを設定する
    self.setCentralWidget(widget)

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果

pyqt

なお、最初にQWidgetオブジェクトを生成し、最後にsetLayout()関数の引数として、QHBoxLayoutオブジェクトを引き渡していることがポイントです。そのうえで、setCentralWidget()でQWidgetオブジェクトを指定すれば、レイアウトを反映できます。メインウィンドウにレイアウトを指定すると、エラーになるので注意が必要です。

QVBoxLayout

「QVBoxLayout」は、ウィジェットを縦に並べるためのレイアウトです。先ほどのQHBoxLayoutオブジェクトと同じく、addWidget()関数でウィジェットを指定すると、指定した順番どおりにウィジェットが縦に並びます。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # ウィジェットを生成する
    # メインウィンドウにレイアウトを直接指定するとエラーになるため、
    # まずWidgetオブジェクトに各要素を入れて、レイアウトを設定してから、
    # Widgetオブジェクトをメインウィンドウに配置する
    widget = QWidget()
    
    # QVBoxLayoutオブジェクトを生成する
    layout = QVBoxLayout()

    # 4つのラベルを生成する
    label_1 = QLabel("テキスト1", self)
    label_2 = QLabel("テキスト2", self)
    label_3 = QLabel("テキスト3", self)
    label_4 = QLabel("テキスト4", self)

    # QVBoxLayoutオブジェクトに4つのラベルを追加する
    layout.addWidget(label_1)
    layout.addWidget(label_2)
    layout.addWidget(label_3)
    layout.addWidget(label_4)

    # Widgetオブジェクトにレイアウトを反映させる
    widget.setLayout(layout)

    # ウィジェットにレイアウトを設定する
    self.setCentralWidget(widget)

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果

pyqt

QGridLayout

「QGridLayout」は、ウィジェットを縦横のグリッド状に並べるためのレイアウトです。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # ウィジェットを生成する
    # メインウィンドウにレイアウトを直接指定するとエラーになるため、
    # まずWidgetオブジェクトに各要素を入れて、レイアウトを設定してから、
    # Widgetオブジェクトをメインウィンドウに配置する
    widget = QWidget()
    
    # QGridLayoutオブジェクトを生成する
    layout = QGridLayout()

    # 4つのラベルを生成する
    label_1 = QLabel("テキスト1", self)
    label_2 = QLabel("テキスト2", self)
    label_3 = QLabel("テキスト3", self)
    label_4 = QLabel("テキスト4", self)

    # QGridLayoutオブジェクトに4つのラベルを追加する
    layout.addWidget(label_1, 0, 0)
    layout.addWidget(label_2, 0, 1)
    layout.addWidget(label_3, 1, 0)
    layout.addWidget(label_4, 1, 1)

    # Widgetオブジェクトにレイアウトを反映させる
    widget.setLayout(layout)

    # ウィジェットにレイアウトを設定する
    self.setCentralWidget(widget)

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果

pyqt

QGridLayoutオブジェクトを生成したうえで、addWidget()関数を呼び出しましょう。第2引数に横方向・第3引数に縦方向の番号を指定することで、ウィジェットがグリッド状に並びます。

QFormLayout

「QFormLayout」は、「ラベル+入力フォーム」のようなセットのウィジェットを、複数並べるためのものです。一連のセットを、QFormLayoutオブジェクトのaddRow()メソッドで並べ、各セットをQHBoxLayoutもしくはQVBoxLayoutで配置します。詳細は以下のサンプルコードのとおりです。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # ウィジェットを生成する
    # メインウィンドウにレイアウトを直接指定するとエラーになるため、
    # まずWidgetオブジェクトに各要素を入れて、レイアウトを設定してから、
    # Widgetオブジェクトをメインウィンドウに配置する
    widget = QWidget()
    
    # QVBoxLayoutオブジェクトを生成する
    # Widgetオブジェクトには1つのレイアウトしか設定できないため、
    # 2つのQFormLayoutオブジェクトを追加してから、
    # QVBoxLayoutオブジェクトをWidgetオブジェクトに反映させる
    layout_0 = QVBoxLayout()

    # 2つのQFormLayoutオブジェクトを生成する
    # ラベル+テキストボックスのペアを配置する
    layout_1 = QFormLayout()
    layout_2 = QFormLayout()

    # 4つのラベルを生成する
    label_1 = QLabel("テキスト1", self)
    label_2 = QLabel("テキスト2", self)
    label_3 = QLabel("テキスト3", self)
    label_4 = QLabel("テキスト4", self)

    # 4つのテキストボックスを生成する
    text_1 = QLineEdit()
    text_2 = QLineEdit()
    text_3 = QLineEdit()
    text_4 = QLineEdit()
    
    # 1つ目のQFormLayoutオブジェクトに、2組のラベル+テキストボックスのペアを追加する
    layout_1.addRow(label_1, text_1)
    layout_1.addRow(label_2, text_2)
    
    # 2つ目のQFormLayoutオブジェクトに、2組のラベル+テキストボックスのペアを追加する
    layout_2.addRow(label_3, text_3)
    layout_2.addRow(label_4, text_4)

    # QVBoxLayoutオブジェクトに、2つのQFormLayoutオブジェクトを追加する
    layout_0.addLayout(layout_1)
    layout_0.addLayout(layout_2)
    
    # Widgetオブジェクトに、QVBoxLayoutオブジェクトのレイアウトを反映させる
    widget.setLayout(layout_0)

    # ウィジェットにレイアウトを設定する
    self.setCentralWidget(widget)

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果

pyqt

上記のサンプルプログラムのように、入力フォームを作成するなどの場合に、QFormLayoutが役立ちます。

ダイアログの種類

ダイアログの種類

ユーザーフレンドリーなGUIアプリを作るためには、「ダイアログ」を活用することも重要です。ダイアログを表示すれば、ユーザーにさまざまな情報を伝えられます。PyQtでは、以下のようにさまざまなダイアログも表示できます。

  • QFileDialog(ファイルダイアログ)
  • QInputDialog(インプットダイアログ)
  • QColorDialog(カラーダイアログ)
  • QFontDialog(フォントダイアログ)
  • QProgressDialog(プログレスダイアログ)
  • QPrintDialog(プリントダイアログ)
  • QMessageBox(メッセージボックス)

QInputDialog(インプットダイアログ)

「QInputDialog(インプットダイアログ)」は、ユーザーにデータを入力してもらうためのダイアログです。「getText」「getMultiLineText」「getItem」「getInt」「getDouble」の5種類があります。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):
    
    # ウィジェットを生成する
    # メインウィンドウにレイアウトを直接指定するとエラーになるため、
    # まずWidgetオブジェクトに各要素を入れて、レイアウトを設定してから、
    # Widgetオブジェクトをメインウィンドウに配置する
    widget = QWidget()
    
    # QVBoxLayoutオブジェクトを生成する
    layout = QVBoxLayout()

    # ボタンを生成する
    single_button = QPushButton("1行テキスト", self)
    multi_button = QPushButton("複数行テキスト", self)
    item_button = QPushButton("アイテム", self)
    int_button = QPushButton("整数値", self)
    double_button = QPushButton("浮動小数点値", self)

    # 各ボタンのサイズをテキストに合わせる
    single_button.adjustSize()
    multi_button.adjustSize()
    item_button.adjustSize()
    int_button.adjustSize()
    double_button.adjustSize()
    
    # 各ボタンのclickedシグナルにスロットを指定する
    single_button.clicked.connect(self.showSingleDialog)
    multi_button.clicked.connect(self.showMultiDialog)
    item_button.clicked.connect(self.showItemDialog)
    int_button.clicked.connect(self.showIntDialog)
    double_button.clicked.connect(self.showDoubleDialog)
    
    # QVBoxLayoutオブジェクトに5つのボタンを追加する
    layout.addWidget(single_button)
    layout.addWidget(multi_button)
    layout.addWidget(item_button)
    layout.addWidget(int_button)
    layout.addWidget(double_button)

    # Widgetオブジェクトにレイアウトを反映させる
    widget.setLayout(layout)

    # ウィジェットにレイアウトを設定する
    self.setCentralWidget(widget)

  # showSingleDialog()メソッド|1行テキストのダイアログを表示する
  def showSingleDialog(self):

    # 「getText」のダイアログを表示する
    # 第2引数はタイトル
    # 第3引数はメッセージ
    text, is_ok = QInputDialog.getText(self, "ダイアログ", "テキストを入力してください")

    # 入力されたテキストを表示する
    if is_ok:
      print(text)
    
  # showMultiDialog()メソッド|複数行テキストのダイアログを表示する
  def showMultiDialog(self):
    
    # 「getMultiLineText」のダイアログを表示する
    # 第2引数はタイトル
    # 第3引数はメッセージ
    text, is_ok = QInputDialog.getMultiLineText(self, "ダイアログ", "テキストを入力してください")

    # 入力されたテキストを表示する
    if is_ok:
      print(text)
    
  # showItemDialog()メソッド|アイテムのダイアログを表示する
  def showItemDialog(self):

    # アイテムのリストを設定する
    items = ["選択肢A", "選択肢B", "選択肢C", "選択肢D", "選択肢E"]
    
    # 「getItem」のダイアログを表示する
    # 第2引数はタイトル
    # 第3引数はメッセージ
    # 第4引数はアイテムのリスト
    # 第5引数はデフォルトの選択肢
    # 第6引数は選択肢を編集可能かどうか
    text, is_ok = QInputDialog.getItem(self, "ダイアログ", "テキストを入力してください",  items, 0, False)

    # 選択されたアイテムを表示する
    if is_ok:
      print(text)
    
  # showIntDialog()メソッド|整数値のダイアログを表示する
  def showIntDialog(self):
    
    # 「getInt」のダイアログを表示する
    # 第2引数はタイトル
    # 第3引数はメッセージ
    # 第4引数は初期値
    # 第5引数は最小値
    # 第6引数は最大値
    # 第7引数は増減値
    text, is_ok = QInputDialog.getInt(self, "ダイアログ", "テキストを入力してください", 0.0, 100.0, -100.0, 5)

    # 入力された整数値を表示する
    if is_ok:
      print(text)
    
  # showDoubleDialog()メソッド|浮動小数点値のダイアログを表示する
  def showDoubleDialog(self):
    
    # 「getDouble」のダイアログを表示する
    # 第2引数はタイトル
    # 第3引数はメッセージ
    # 第4引数は初期値
    # 第5引数は最小値
    # 第6引数は最大値
    # 第7引数は小数部の桁数
    text, is_ok = QInputDialog.getDouble(self, "ダイアログ", "テキストを入力してください", 0.0, -100.0, 100.0, 3)
    
    # 入力された浮動小数点値を表示する
    if is_ok:
      print(text)

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
メイン画面

pyqt

getText

pyqt

getMultiLineText

pyqt

getItem

pyqt

getInt

pyqt

getDouble

pyqt

各ボタンをクリックすることで、インプットダイアログが表示されます。ユーザーの入力値は、ダイアログの戻り値として取得できます。

QFileDialog(ファイルダイアログ)

「QFileDialog(ファイルダイアログ)」は、ファイル入出力を行うためのダイアログです。ファイルを開く場合は「QFileDialog.getOpenFileName」、保存する場合は「QFileDialog.getSaveFileName」を使用します。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # 2つのボタンを生成する
    open_button = QPushButton("ファイルを開く", self)
    save_button = QPushButton("ファイルを保存する", self)

    # 各ボタンの位置を設定する
    open_button.move(110, 100)
    save_button.move(100, 200)

    # 各ボタンのサイズをテキストに合わせる
    open_button.adjustSize()
    save_button.adjustSize()
    
    # 各ボタンのclickedシグナルにメソッドをスロットとして指定する
    open_button.clicked.connect(self.openFile)
    save_button.clicked.connect(self.saveFile)

  # openFile()メソッド|ファイルを開くダイアログを表示する
  def openFile(self):
    
    # QFileDialog.getOpenFileName()メソッドで、ファイルを開くダイアログを表示する
    # 第2引数はダイアログのタイトル、第3引数は最初のパス、第4引数はフィルターを設定する
    filename = QFileDialog.getOpenFileName(self, "ファイルを開く", "./", "Image files (*.bmp *.jpg *.png *.tif);;Any files (*.*)")
    
    # ファイルが選択されている場合は、ファイル名を表示する
    if filename[0] != "":
      print(f"「{filename[0]}」が選択されました")
      
  # saveFile()メソッド|ファイルを開くダイアログを表示する
  def saveFile(self):
    
    # QFileDialog.getSaveFileName()メソッドで、ファイルを開くダイアログを表示する
    # 第2引数はダイアログのタイトル、第3引数は最初のパス、第4引数はフィルターを設定する
    filename = QFileDialog.getSaveFileName(self, "ファイルを保存する", "./", "Image files (*.bmp *.jpg *.png *.tif);;Any files (*.*)")
    
    # ファイルが選択されている場合は、ファイル名を表示する
    if filename[0] != "":
      print(f"「{filename[0]}」が選択されました")

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期画面

pyqt

ファイルを開く

pyqt

ファイルを保存する

pyqt

なお、ダイアログ関数の引数は、第2引数がダイアログのタイトル・第3引数が最初のパス・第4引数がフィルターとなっています。フィルターを設定することで、どの拡張子のファイルをオープン・セーブできるか指定可能です。

QColorDialog(カラーダイアログ)

「QColorDialog.getColor()メソッド」で、カラーダイアログを表示できます。カラーダイアログは、ユーザーが自由に「色」を選べるので便利です。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):
    
    # ウィジェットを生成する
    # メインウィンドウにレイアウトを直接指定するとエラーになるため、
    # まずWidgetオブジェクトに各要素を入れて、レイアウトを設定してから、
    # Widgetオブジェクトをメインウィンドウに配置する
    widget = QWidget()
    
    # QVBoxLayoutオブジェクトを生成する
    layout = QVBoxLayout()

    # ボタンを生成する
    button = QPushButton("カラー", self)

    # 各ボタンのサイズをテキストに合わせる
    button.adjustSize()
    
    # 各ボタンのclickedシグナルに「showColorDialog()メソッド」をスロットとして指定する
    button.clicked.connect(self.showColorDialog)
    
    # QVBoxLayoutオブジェクトにボタンを追加する
    layout.addWidget(button)

    # Widgetオブジェクトにレイアウトを反映させる
    widget.setLayout(layout)

    # ウィジェットにレイアウトを設定する
    self.setCentralWidget(widget)

  # showColorDialog()メソッド|カラーダイアログを表示する
  def showColorDialog(self):

    # QColorDialogダイアログを表示する
    # 第1引数は初期設定のカラー
    # 第3引数はダイアログのタイトル
    # 第4引数はオプション(ここでは「アルファチャンネルを表示」を指定)
    color = QColorDialog.getColor(Qt.white, self, "カラーダイアログ", QColorDialog.ShowAlphaChannel)

    # 有効なカラーが指定された場合は、コンソール画面にRGBAの順番で表示する
    if color.isValid():
      print(color.getRgb())

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期画面

pyqt

カラーダイアログ

pyqt

色を指定するとき

pyqt

コンソール画面

pyqt

ダイアログの「Pick Screen Color」を選べば、画面上の色をピックアップできるので非常に便利です。

QFontDialog(フォントダイアログ)

「QFontDialog(フォントダイアログ)」は、フォントを選択するためのダイアログ。GUI画面上に設置することで、ユーザーが自由にフォントを選択できます。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):
    
    # ウィジェットを生成する
    # メインウィンドウにレイアウトを直接指定するとエラーになるため、
    # まずWidgetオブジェクトに各要素を入れて、レイアウトを設定してから、
    # Widgetオブジェクトをメインウィンドウに配置する
    widget = QWidget()
    
    # QVBoxLayoutオブジェクトを生成する
    layout = QVBoxLayout()

    # ボタンを生成する
    button = QPushButton("フォント", self)

    # 各ボタンのサイズをテキストに合わせる
    button.adjustSize()
    
    # 各ボタンのclickedシグナルに「showFontDialog()メソッド」をスロットとして指定する
    button.clicked.connect(self.showFontDialog)
    
    # QVBoxLayoutオブジェクトにボタンを追加する
    layout.addWidget(button)

    # Widgetオブジェクトにレイアウトを反映させる
    widget.setLayout(layout)

    # ウィジェットにレイアウトを設定する
    self.setCentralWidget(widget)

  # showFontDialog()メソッド|フォントダイアログを表示する
  def showFontDialog(self):

    # QFontDialogダイアログを表示する
    # 第1引数は初期設定のフォント
    # 第3引数はダイアログのタイトル
    font, is_ok = QFontDialog.getFont(QtGui.QFont("メイリオ", 10), self, "フォントダイアログ")

    # コンソール画面にフォント情報で表示する
    if is_ok:
      print(f"フォント名「{font.family()}」\nサイズ「{font.pointSize()}」\nウェイト「{font.weight()}」\nイタリック「{font.italic()}」\nボールド「{font.bold()}」\nStrikeout「{font.strikeOut()}」\nUnderline「{font.underline()}」")

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期画面

pyqt

フォントダイアログ

pyqt

フォント選択時

pyqt

コンソール画面

pyqt

QProgressDialog(プログレスダイアログ)

「QProgressDialog(プログレスダイアログ)」は、プロセスの進行状況を表示するためのダイアログです。QProgressDialogの生成時に、メッセージと最小値・最大値を指定でき、setWindowModalityでモダリティの指定もできます。モーダルダイアログを使用し、プログレスダイアログを表示する手順は以下のとおりです。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# 「timeモジュール」をインポートする
import time

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):
    
    # ウィジェットを生成する
    # メインウィンドウにレイアウトを直接指定するとエラーになるため、
    # まずWidgetオブジェクトに各要素を入れて、レイアウトを設定してから、
    # Widgetオブジェクトをメインウィンドウに配置する
    widget = QWidget()
    
    # QVBoxLayoutオブジェクトを生成する
    layout = QVBoxLayout()

    # ボタンを生成する
    button = QPushButton("プログラム処理を進行する", self)

    # 各ボタンのサイズをテキストに合わせる
    button.adjustSize()
    
    # 各ボタンのclickedシグナルに「showProgressDialog()メソッド」をスロットとして指定する
    button.clicked.connect(self.showProgressDialog)
    
    # QVBoxLayoutオブジェクトにボタンを追加する
    layout.addWidget(button)

    # Widgetオブジェクトにレイアウトを反映させる
    widget.setLayout(layout)

    # ウィジェットにレイアウトを設定する
    self.setCentralWidget(widget)

  # showProgressDialog()メソッド|プログレスダイアログを表示する
  def showProgressDialog(self):

    # プログレスダイアログを表示する
    # 第1引数はメッセージ
    # 第2引数は処理を中止するボタンのテキスト
    # 第3引数は進行状況の最小値
    # 第4引数は進行状況の最大値
    progress = QProgressDialog("処理を行っています…", "中止する", 0, 100, self)

    # ウィンドウのモダリティを設定する
    # 「Qt.WindowModal(モーダルダイアログ)」もしくは「Qt.NonModal(モードレスダイアログ)」を選択
    # Qt.WindowModalは、ダイアログが終了するまでメインウィンドウを操作できない
    # Qt.NonModalは、ダイアログ進行中でもメインウィンドウを操作できる
    # Qt.WindowModalを選ぶのが無難で、Qt.NonModalは基本的に使わない
    progress.setWindowModality(Qt.WindowModal)

    # ダイアログのタイトルを設定する
    progress.setWindowTitle("プログレスダイアログ")

    # ダイアログのサイズを設定する
    progress.setFixedSize(500, 250)

    # ダイアログを表示する
    progress.show()

    # forループでダイアログを進行させる
    for i in range(100):
      # 無限forループなどを回していると、GUI画面が固まってしまう。
      # そこで、毎ループ「QApplication.processEvents()メソッド」を呼び出すことにより、
      # 未処理のイベントを済ませてから、forループの処理に戻ることができる。
      # 引数に「QEventLoop.ExcludeUserInputEvents」を指定すると、
      # ウィジェットなどに対するユーザーの入力を防げるため、想定外の動作を防げて安全
      QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)

      # ダイアログの進行度を設定する
      progress.setValue(i)

      # 0.05秒だけ待機する
      time.sleep(0.05)

      # キャンセルボタンがクリックされたときは、処理を終了する
      if progress.wasCanceled():
        break;
      
    # 最後にダイアログの進行度をMAXにする
    progress.setValue(100);

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期画面

pyqt

ダイアログ

pyqt

処理進行中

pyqt

大容量ファイルの入出力など時間がかかる処理を行うときは、プログレスダイアログを表示すると、ユーザーフレンドリーなGUIアプリになるでしょう。

QPrintDialog(プリントダイアログ)

「QPrintDialog(プリントダイアログ)」は、ドキュメントを印刷するためのダイアログです。まず、QPrinterオブジェクトを準備したうえで、QPrintDialogを生成します。戻り値が「QDialog.Accepted」であれば、実際の印刷処理を行います。今回は、ユーザーがテキストボックスに入力したテキストを印刷するための、サンプルコードをご紹介します。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「QTextDocument」「QPrintDialog」「QPrinter」モジュールをインポートする
from PyQt5.QtGui import QTextDocument
from PyQt5.QtPrintSupport import QPrintDialog, QPrinter

# 「sipモジュール」をインポートする
import sip

# 「timeモジュール」をインポートする
import time

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):
    
    # ウィジェットを生成する
    # メインウィンドウにレイアウトを直接指定するとエラーになるため、
    # まずWidgetオブジェクトに各要素を入れて、レイアウトを設定してから、
    # Widgetオブジェクトをメインウィンドウに配置する
    widget = QWidget()
    
    # QVBoxLayoutオブジェクトを生成する
    layout = QVBoxLayout()

    # ラベルを生成する
    label = QLabel("テキストを入力してください", self)
    
    # テキストボックスを生成する
    self.text = QTextEdit(self)

    # ボタンを生成する
    button = QPushButton("印刷する", self)

    # 各ボタンのサイズをテキストに合わせる
    button.adjustSize()
    
    # 各ボタンのclickedシグナルに「showPrinterDialog()メソッド」をスロットとして指定する
    button.clicked.connect(self.showPrinterDialog)
    
    # QVBoxLayoutオブジェクトに各ウィジェットを追加する
    layout.addWidget(label)
    layout.addWidget(self.text)
    layout.addWidget(button)

    # Widgetオブジェクトにレイアウトを反映させる
    widget.setLayout(layout)

    # ウィジェットにレイアウトを設定する
    self.setCentralWidget(widget)

  # showPrinterDialog()メソッド|プリンターダイアログを表示する
  def showPrinterDialog(self):

    # QPrinterオブジェクトを生成する
    printer = QPrinter(QPrinter.HighResolution)

    # QPrintDialogを表示する
    dialog = QPrintDialog(printer, self)

    # ダイアログで「印刷」がクリックされたら、入力されたテキストを印刷する
    if dialog.exec() == QDialog.Accepted:

      # QTextDocumentオブジェクトを生成する
      document = QTextDocument();
      
      # ユーザーが入力したテキストをドキュメントに反映する
      document.setPlainText(self.text.toPlainText());
      
      # ドキュメントを印刷する
      document.print(printer);

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
テキスト入力画面

pyqt

プリンターダイアログ

pyqt

PDF化したドキュメント

pyqt

Windows PCの場合は、「Microsoft Print to PDF」を選択すると、仮想プリンターとしてテキストドキュメントをPDF化できます。ドキュメントをPDF化する機会は多いので、実用的なプログラムだといえるでしょう。

QMessageBox(メッセージボックス)

「QMessageBox(メッセージボックス)」は、ユーザーに単純なメッセージを表示するためのダイアログです。以下のサンプルコードのように、「information(情報)」「warning(警告)」「critical(エラー)」「question(確認)」の4種類のダイアログが選べます。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):
    
    # ウィジェットを生成する
    # メインウィンドウにレイアウトを直接指定するとエラーになるため、
    # まずWidgetオブジェクトに各要素を入れて、レイアウトを設定してから、
    # Widgetオブジェクトをメインウィンドウに配置する
    widget = QWidget()
    
    # QVBoxLayoutオブジェクトを生成する
    layout = QVBoxLayout()

    # ボタンを生成する
    button_information = QPushButton("情報", self)
    button_warning = QPushButton("警告", self)
    button_critical = QPushButton("エラー", self)
    button_question = QPushButton("確認", self)
    
    # 各ボタンのclickedシグナルのスロットを指定する
    button_information.clicked.connect(self.showInformationBox)
    button_warning.clicked.connect(self.showWarningBox)
    button_critical.clicked.connect(self.showCriticalBox)
    button_question.clicked.connect(self.showQuestionBox)
    
    # QVBoxLayoutオブジェクトに各ボタンを追加する
    layout.addWidget(button_information)
    layout.addWidget(button_warning)
    layout.addWidget(button_critical)
    layout.addWidget(button_question)

    # Widgetオブジェクトにレイアウトを反映させる
    widget.setLayout(layout)

    # ウィジェットにレイアウトを設定する
    self.setCentralWidget(widget)

  # showInformationBox()メソッド|Informationメッセージボックスを表示する
  def showInformationBox(self):
    QMessageBox.information(self, "情報", "メッセージ")

  # showWarningBox()メソッド|Warningメッセージボックスを表示する
  def showWarningBox(self):
    QMessageBox.warning(self, "警告", "メッセージ")

  # showCriticalBox()メソッド|Criticalメッセージボックスを表示する
  def showCriticalBox(self):
    QMessageBox.critical(self, "エラー", "メッセージ")

  # showQuestionBox()メソッド|Questionメッセージボックスを表示する
  def showQuestionBox(self):
    QMessageBox.question(self, "確認", "メッセージ")

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期画面

pyqt

情報

警告

pyqt

エラー

pyqt

確認

pyqt

PyQtでは、カスタムのメッセージボックスも作成できるのが魅力です。QMessageBoxを生成し、追加したいボタンをaddButton()関数で指定します。この関数では「StandardButton」を指定でき、以下のような種類があります。

ボタン 概要 役割
QMessageBox.Ok 了解 AcceptRole
QMessageBox.Open 開く AcceptRole
QMessageBox.Save 保存 AcceptRole
QMessageBox.Cancel キャンセル RejectRole
QMessageBox.Close 閉じる RejectRole
QMessageBox.Discard 破棄 DestructiveRole
QMessageBox.Apply 適用する ApplyRole
QMessageBox.Reset リセット ResetRole
QMessageBox.RestoreDefaults デフォルトに戻す ResetRole
QMessageBox.Help ヘルプ HelpRole
QMessageBox.SaveAll すべて保存 AcceptRole
QMessageBox.Yes はい YesRole
QMessageBox.YesToAll すべてはい YesRole
QMessageBox.No いいえ NoRole
QMessageBox.NoToAll すべていいえ NoRole
QMessageBox.Abort 異常終了 RejectRole
QMessageBox.Retry 再試行 AcceptRole
QMessageBox.Ignore 無視 AcceptRole
QMessageBox.NoButton ボタンなし なし

上記以外のオリジナルのボタンを追加したいときは、addButtonの第1引数にボタンテキスト、第2引数に「ボタンの役割」を指定します。ボタンの役割として、以下のようなものを指定できます。

役割 概要
InvalidRole 無効
AcceptRole 受諾(OK)
RejectRole 拒否(Canel)
DestructiveRole 変更の破棄
ActionRole 要素の変更
HelpRole ヘルプの要求
YesRole 「はい」ボタン
NoRole 「いいえ」ボタン
ResetRole デフォルトの復帰
ApplyRole 変更の適用

なお、exec()メソッドの戻り値は「StandardButton」しかないため、オリジナルボタンを使用した場合は、このメソッドでクリックされたボタンの判定ができません。そのため、clickedButton()関数を使用する必要があります。メッセージボックスの表示後、QMessageBoxオブジェクトの「clickedButton()」を呼び出すことで、ユーザーが選択したボタンがわかります。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui

# 「sipモジュール」をインポートする
import sip

# 「timeモジュール」をインポートする
import time

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):
    
    # ウィジェットを生成する
    # メインウィンドウにレイアウトを直接指定するとエラーになるため、
    # まずWidgetオブジェクトに各要素を入れて、レイアウトを設定してから、
    # Widgetオブジェクトをメインウィンドウに配置する
    widget = QWidget()
    
    # QVBoxLayoutオブジェクトを生成する
    layout = QVBoxLayout()

    # 2つのボタンを生成する
    button_default = QPushButton("デフォルトのメッセージボックス", self)
    button_original = QPushButton("オリジナルのメッセージボックス", self)
    
    # 各ボタンのclickedシグナルのスロットを指定する
    button_default.clicked.connect(self.showDefaultMessageBox)
    button_original.clicked.connect(self.showOriginalMessageBox)
    
    # QVBoxLayoutオブジェクトに各ボタンを追加する
    layout.addWidget(button_default)
    layout.addWidget(button_original)

    # Widgetオブジェクトにレイアウトを反映させる
    widget.setLayout(layout)

    # ウィジェットにレイアウトを設定する
    self.setCentralWidget(widget)

  # showDefaultMessageBox()メソッド|デフォルトのカスタムメッセージボックスを表示する
  def showDefaultMessageBox(self):

    # QMessageBoxオブジェクトを生成する
    message_box = QMessageBox(self)
    
    # メッセージボックスのタイトルを設定する
    message_box.setWindowTitle("確認")

    # メッセージボックスのテキストを設定する
    message_box.setText("これでよろしいですか?")

    # 「確認アイコン」を設定する
    message_box.setIcon(QMessageBox.Question)

    # 「Yes」「No」「Cancel」のボタンを追加する
    message_box.addButton(QMessageBox.Yes)
    message_box.addButton(QMessageBox.No)
    message_box.addButton(QMessageBox.Cancel)

    # デフォルトのボタンを「Cencel」に設定する
    message_box.setDefaultButton(QMessageBox.Cancel)

    # メッセージボックスを表示する
    result = message_box.exec()
    
    # 「Yes」が選択されたら処理開始のメッセージを表示する
    if result == QMessageBox.Yes:
      print("処理を開始します…")

  # showOriginalMessageBox()メソッド|オリジナルのカスタムメッセージボックスを表示する
  def showOriginalMessageBox(self):
    
    # QMessageBoxオブジェクトを生成する
    message_box = QMessageBox(self)
    
    # メッセージボックスのタイトルを設定する
    message_box.setWindowTitle("エラー")
    
    # メッセージボックスのテキストを設定する
    message_box.setText("処理中に致命的なエラーが発生しました")
    
    # 「エラーアイコン」を設定する
    message_box.setIcon(QMessageBox.Critical)

    # 「再チャレンジする」ボタンを「受諾」用途で追加する
    button_1 = message_box.addButton("再チャレンジする", QMessageBox.AcceptRole)
    
    # 「データを破棄する」ボタンを「破棄」用途で追加する
    button_2 = message_box.addButton("データを破棄する", QMessageBox.DestructiveRole)
    
    # 「前の画面に戻る」ボタンを「リセット」用途で追加する
    button_3 = message_box.addButton("前の画面に戻る", QMessageBox.ResetRole)
    
    # デフォルトのボタンを「Cencel」に設定する
    message_box.setDefaultButton(button_3)
    
    # メッセージボックスを表示する
    message_box.exec()

    # clickedButton()メソッドで、クリックしたボタンを取得する
    clicked = message_box.clickedButton()

    # 「再チャレンジする」が選択された場合
    if clicked == button_1:
      print("「再チャレンジする」が選択されました")
      
    # 「データを破棄する」が選択された場合
    elif clicked == button_2:
      print("「データを破棄する」が選択されました")
      
    # 「前の画面に戻る」が選択された場合
    else:
      print("「前の画面に戻る」が選択されました")

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期画面

pyqt

デフォルトのメッセージボックス

pyqt

オリジナルのメッセージボックス

pyqt

コンソール画面

pyqt

上記のサンプルプログラムでは、「デフォルトのメッセージボックス」と「オリジナルのメッセージボックス」の双方を表示し、その違いを確認できます。

PyQtで役立つ応用テクニック

PyQtで役立つ応用テクニック

ここまでに解説したさまざまなメソッドやウィジェットの知識を活かすと、よりハイレベルなGUIアプリを作成できることを覚えておきましょう。今回は一例として、以下の2つの応用例をご紹介します。

  • 簡易的なテキストエディタを作成する
  • 「PyQt」と「Matplotlib」を組み合わせてグラフを作成する

簡易的なテキストエディタを作成する

ツールボタンやアイコン、テキストボックスやファイルダイアログなどを組み合わせると、簡易的なテキストエディタを作成できます。テキストファイルの読み込みや保存に加えて、テキストボックスのフォントを変更することも可能です。以下のサンプルコードを参考にして、オリジナルのテキストエディタを作ってみましょう。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「QtGuiモジュール」をインポートする
from PyQt5 import QtGui
from PyQt5.QtGui import QIcon
from PyQt5.QtGui import QPixmap

# 「sipモジュール」をインポートする
import sip

# 「timeモジュール」をインポートする
import time

# 「threadingモジュール」をインポートする
import threading

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):

    # QWidgetクラスを初期化する
    super().__init__()

    # PyQtのウィンドウを生成する
    self.createWindow()

  # createWindow()メソッド|PyQtのウィンドウを生成する
  def createWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)

    # ウィジェットを生成する
    self.initWidget()

    # ウィンドウを表示する
    self.show()
    
  # initWidget()メソッド|ウィジェットを生成する
  def initWidget(self):

    # ウィジェットを生成する
    widget = QWidget()
    
    # 4つのボタンを生成する
    button_open = QToolButton()
    button_save = QToolButton()
    button_font = QToolButton()
    button_desc = QToolButton()
    
    # 各ボタンのアイコンを設定する
    button_open.setIcon(QIcon(self.style().standardPixmap(QStyle.SP_DialogOpenButton)))
    button_save.setIcon(QIcon(self.style().standardPixmap(QStyle.SP_DialogSaveButton)))
    button_font.setIcon(QIcon(self.style().standardPixmap(QStyle.SP_FileDialogContentsView)))
    button_desc.setIcon(QIcon(self.style().standardPixmap(QStyle.SP_MessageBoxQuestion)))
    
    # 各ボタンのテキストを設定する
    button_open.setText("読み込み");
    button_save.setText("保存");
    button_font.setText("フォント");
    button_desc.setText("概要");
   
    # テキストの表示形式を設定する
    # 「ToolButtonTextBesideIcon」はアイコンの横
    # 「ToolButtonTextUnderIcon」はアイコンの下
    button_open.setToolButtonStyle(Qt.ToolButtonTextUnderIcon);
    button_save.setToolButtonStyle(Qt.ToolButtonTextUnderIcon);
    button_font.setToolButtonStyle(Qt.ToolButtonTextUnderIcon);
    button_desc.setToolButtonStyle(Qt.ToolButtonTextUnderIcon);
    
    # clickedシグナルに「qApp.quit()メソッド」をスロットとして指定する
    # ボタンを押すとプログラムが終了する
    button_open.clicked.connect(self.button_open_clicked)
    button_save.clicked.connect(self.button_save_clicked)
    button_font.clicked.connect(self.button_font_clicked)
    button_desc.clicked.connect(self.button_desc_clicked)

    # QGridLayoutオブジェクトを生成する
    layout = QGridLayout()
    
    # 各ボタンを配置する
    layout.addWidget(button_open, 0, 0, 1, 1)
    layout.addWidget(button_save, 0, 1, 1, 1)
    layout.addWidget(button_font, 0, 2, 1, 1)
    layout.addWidget(button_desc, 0, 3, 1, 1)
    
    # テキストボックスを生成する
    self.text = QTextEdit("テキストを入力してください", self, font = QtGui.QFont("メイリオ", 10))
    
    # テキストボックスを配置する
    layout.addWidget(self.text, 1, 0, 1, 5)
    
    # レイアウト適用済みのウィジェットをメインウィンドウに追加する
    widget.setLayout(layout)
    self.setCentralWidget(widget)
    
  # button_open_clicked()メソッド|テキストファイルを読み込んでテキストボックスに表示する
  def button_open_clicked(self):
    
    # QFileDialog.getOpenFileName()メソッドで、ファイルを開くダイアログを表示する
    # 第2引数はダイアログのタイトル、第2引数は最初のパス、第4引数はフィルターを設定する
    filename = QFileDialog.getOpenFileName(self, "ファイルを開く", "./", "Text files (*.txt);;Any files (*.*)")
    
    # ファイルが選択されている場合は、ファイルの中身をテキストボックスに反映する
    if filename[0] != "":

      # 「読み込みモード」でファイルを開き、テキストデータを読み込む
      data = open(filename[0], "r", encoding = "UTF-8")
      text = data.read()
      data.close()

      # テキストボックスにテキストを反映させる
      self.text.setPlainText(text)
      
      # プログレスバーを表示する
      self.progress()

  # button_save_clicked()メソッド|テキストボックスのデータをテキストファイルに書き出す
  def button_save_clicked(self):
    
    # QFileDialog.getSaveFileName()メソッドで、ファイルを開くダイアログを表示する
    # 第2引数はダイアログのタイトル、第2引数は最初のパス、第4引数はフィルターを設定する
    filename = QFileDialog.getSaveFileName(self, "ファイルを保存する", "./", "Text files (*.txt);;Any files (*.*)")
    
    # ファイルが選択されている場合は、テキストボックスのデータをテキストファイルに書き出す
    if filename[0] != "":
      
      # 「書き込みモード」でファイルを開き、テキストデータを書き出す
      data = open(filename[0], "w", encoding = "UTF-8")
      data.write(self.text.toPlainText())
      data.close()
      
      # プログレスバーを表示する
      self.progress()

  # button_font_clicked()メソッド|「フォント」ボタンをクリックしたときの処理を行う
  def button_font_clicked(self):
    
    # QFontDialogダイアログを表示する
    # 第1引数は初期設定のフォント
    # 第3引数はダイアログのタイトル
    font, is_ok = QFontDialog.getFont(QtGui.QFont("メイリオ", 10), self, "フォントダイアログ")

    # コンソール画面にフォント情報で表示する
    if is_ok:

      # テキストボックスのフォントに反映する
      self.text.setFont(QtGui.QFont(font.family(), pointSize = font.pointSize(), italic = font.italic(), weight = font.weight()))
      
  # button_desc_clicked()メソッド|「概要」ボタンをクリックしたときの処理を行う
  def button_desc_clicked(self):
    
    # メッセージボックスでプログラムの概要を表示する
    QMessageBox.information(self, "情報", "本プログラムは簡易的なテキストエディタです。\nテキストファイルの読み込みと書き出しが行えます。")

  # progress()メソッド|プログレスバーを進行させる
  def progress(self):

    # プログレスバーを生成する
    bar = QProgressBar()
    
    # メインウィンドウのステータスバーに、プログレスバーを埋め込む
    self.statusBar().addWidget(bar);

    # プログレスバーの進行度
    value = 0

    # プログレスバーが100になるまで無限ループを回す
    while True:
      # 無限forループなどを回していると、GUI画面が固まってしまう。
      # そこで、毎ループ「QApplication.processEvents()メソッド」を呼び出すことにより、
      # 未処理のイベントを済ませてから、forループの処理に戻ることができる。
      # 引数に「QEventLoop.ExcludeUserInputEvents」を指定すると、
      # ウィジェットなどに対するユーザーの入力を防げるため、想定外の動作を防げて安全
      QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)

      # プログレスバーの値を更新する
      bar.setValue(value)

      # プログレスバーを1だけ進める
      # 値が100を超えた場合は処理を終了する
      value += 1
      if(value > 100):
        break

      # 0.001秒だけ待機する
      time.sleep(0.001)

    # 処理の完了後は、ステータスバーからプログレスバーを削除して、完了メッセージを表示する
    self.statusBar().removeWidget(bar)
    self.statusBar().showMessage("処理が完了しました!")

# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":

  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期画面

「読み込みボタン」クリック時

pyqt

「保存ボタン」クリック時

pyqt

「フォントボタン」クリック時

pyqt

「概要ボタン」クリック時

pyqt

フォント変更後

pyqt

上記のように、GUI画面上には4つのツールボタンが表示され、その下にテキストボックスがあります。それぞれのボタンをクリックすると、ファイルの読み込みや保存、フォントの設定などが可能です。なお、本プログラムで作成したテキストファイルは、メモ帳などのテキストエディタでも使えます。

さらに機能を発展させるために、文字列の検索や置換などの機能を搭載すると、より便利なテキストエディタになるでしょう。

「PyQt」と「Matplotlib」を組み合わせてグラフを作成する

GUIライブラリの「PyQt」と、グラフ描画用のライブラリである「Matplotlib」を組み合わせれば、GUI画面にグラフを表示することもできます。詳細は以下のサンプルコードのとおりです。

//サンプルプログラム

# coding: UTF-8

# 「sysモジュール」をインポートする
import sys

# 「datetimeモジュール」をインポートする
import datetime

# 「localeモジュール」をインポートする
import locale

# 「randomモジュール」をインポートする
import random

# 「PyQt」のモジュール群をインポートする
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# 「matplotlib」のモジュール群をインポートする
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as pyplot

# Programクラス|PyQtの処理を実行する
# さまざまな機能を搭載した「QMainWindowクラス」を継承する
class Program(QMainWindow):

  # コンストラクタ
  def __init__(self):
    
    # QWidgetクラスを初期化する
    super().__init__()
        
    # システムロケールを設定する
    locale.setlocale(locale.LC_ALL, "")
    
    # PyQtのウィンドウを生成する
    self.initWindow()

  def initWindow(self):
    
    # ウィンドウのタイトルを設定する
    self.setWindowTitle("PyQtサンプルプログラム")

    # ウィンドウのサイズを設定する
    self.setGeometry(0, 0, 640, 480)
    
    # ステータスバーを表示する
    self.statusBar()
    
    # メニューバーを表示する
    self.setMenuBar()

    # グラフを表示する
    self.setPlot()

    # ウィンドウを表示する
    self.show()

  # setMenuBar()メソッド|メニューバーを生成する
  def setMenuBar(self):

    # メニューバーを生成する
    menubar = self.menuBar()

    # メニューバーに「ファイル」項目を追加する
    fileMenu = menubar.addMenu("ファイル")

    # 「終了」アクションを作成する
    exitAction = QAction("終了", self)
    
    # 「終了」アクションのショートカットを設定する
    exitAction.setShortcut("Ctrl+Q")

    # 「終了」アクションのステータスバーのメッセージを設定する
    exitAction.setStatusTip("プログラムを終了します")

    # 「終了」アクションとqApp.quit()メソッドを関連付ける
    exitAction.triggered.connect(qApp.quit)

    # メニューバーの「ファイル」項目に「終了」アクションを追加する
    fileMenu.addAction(exitAction)
    
  # setPlot()メソッド|グラフを生成する
  def setPlot(self):

    # ウィジェットを生成する
    self.widget = QWidget()

    # グラフを描画するための「PlotCanvasクラス」のインスタンスを生成する
    self.canvas = PlotCanvas(self)

    # 「新規」と「削除」のボタンを作成する
    self.plot_button = QPushButton("新規グラフ", self)
    self.clear_button = QPushButton("グラフ削除", self)
    
    # 「新規」と「削除」のボタンをPlotCanvasクラスの「plot()」と「clear()」と紐づける
    self.plot_button.clicked.connect(self.canvas.plot)
    self.clear_button.clicked.connect(self.canvas.clear)

    # ウィジェット配置用にレイアウトを生成する
    main_layout = QGridLayout()

    # 各ウィジェットをレイアウトに配置する
    main_layout.addWidget(self.canvas, 0, 0, 1, 5)
    main_layout.addWidget(self.plot_button, 1, 1, 1, 1)
    main_layout.addWidget(self.clear_button, 1, 3, 1, 1)
    
    # ウィジェットにレイアウトを設定する
    self.widget.setLayout(main_layout)

    # ウィジェットをメインウィンドウに追加する
    self.setCentralWidget(self.widget)

    # QTimerを初期化する
    timer = QTimer(self)

    # timeoutシグナルに「getDateTime()メソッド」をスロットとして指定する
    timer.timeout.connect(self.getDateTime)

    # タイマーの動作を開始する
    timer.start()

  # getDateTime()メソッド|ステータスバーに現在日時を表示する
  def getDateTime(self):

    # 現在の日時を取得する
    time = datetime.datetime.today()

    # 取得した日時をフォーマット済み文字列形式に変換する
    string = time.strftime(u"%Y年%m月%d日 %H時%M分%S秒")

    # ステータスバーに現在日時を表示する
    self.statusBar().showMessage(f"現在時刻:{string}")
    
# PlotCanvasクラス|グラフを描画する
# グラフ関連の機能を搭載した「FigureCanvasクラス」を継承する
class PlotCanvas(FigureCanvas):
  
  # コンストラクタ
  def __init__(self, parent):

    # 全体の描画領域「Figureオブジェクト」を生成する
    self.figure = Figure()

    # グラフの描画領域「Axesオブジェクト」を生成する
    # 引数は「縦方向に1つ・横方向に1つのプロットを描画し、その1番目のプロットを生成する」という意味で、1つのプロットしか描画しない場合は「111」固定でOK
    self.axes = self.figure.add_subplot(111)

    # 親クラスのコンストラクタを呼び出す
    super(PlotCanvas, self).__init__(self.figure)

    # 親オブジェクトを設定する
    self.setParent(parent)
    
    # グラフを描画する
    self.plot()
    
  # plot()メソッド|グラフを描画する
  def plot(self):

    # -100.0から+100.0の範囲で、25個のランダムな浮動小数点値を生成する
    self.data = [random.randrange(-100.0, +100.0) for i in range(25)]

    # グラフを消去する
    self.axes.cla()

    # グラフのタイトルを付ける
    # ここで日本語などのマルチバイト文字を使用すると文字化けするので要注意
    self.axes.set_title("Random Graph")

    # グラフを描画する
    # 描画形式を「赤色・破線・三角」にする
    self.axes.plot(self.data, "r--^")
    
    # 全体を再描画する
    self.draw()

  # clear()メソッド|グラフを消去する
  def clear(self):

    # グラフを消去する
    self.axes.cla()

    # グラフを再描画する
    self.draw()
        
# main()メソッド|プログラムのエントリーポイント
if __name__ == "__main__":
  
  # PyQtを初期化する
  app = QApplication(sys.argv)

  # Programクラスのインスタンスを生成する
  program = Program()

  # プログラムを終了する
  sys.exit(app.exec_())


//実行結果
初期状態

pyqt

更新時

pyqt

削除時

pyqt

GUI画面上の「新規グラフ」ボタンをクリックすると、新しいグラフがランダムに描画されます。「グラフ削除」ボタンは、グラフを削除するためのものです。

なお、グラフ描画ライブラリ「Matplotlib」については、以下の記事で詳しく解説しているので、ぜひ参考にしてみてください。

PythonのMatplotlibでデータを可視化!使い方やテクニックを解説
https://one-div.com/programming/python/how-to-python-matplotlib

PythonのPyQtの活用で高機能なGUIアプリが作れる

PythonのPyQtの活用で高機能なGUIアプリが作れる

Pythonの「PyQt」を活用すると、高機能かつデザイン性が優れたGUIアプリが作れます。PyQtは現在でもアップデートが続いているモダンなアプリなので、PythonでGUIプログラミングを習得したい場合は、PyQtにチャレンジしてみることをおすすめします。今回ご紹介したウィジェットやテクニックを活用すれば、ハイレベルなGUIアプリを開発できるでしょう。

アクセスランキング 人気のある記事をピックアップ!

    コードカキタイがオススメする記事!

    1. 子供におすすめのプログラミングスクール10選!学習メリットや教室選びのコツも紹介

      2024.01.26

      子供におすすめのプログラミングスクール10選!学習メリットや教室選びのコツも紹介

      #プログラミングスクール

    2. 【完全版】大学生におすすめのプログラミングスクール13選!選ぶコツも詳しく解説

      2022.01.06

      【完全版】大学生におすすめのプログラミングスクール13選!選ぶコツも詳しく解説

      #プログラミングスクール

    3. 【未経験でも転職可】30代におすすめプログラミングスクール8選!

      2024.01.26

      【未経験でも転職可】30代におすすめプログラミングスクール8選!

      #プログラミングスクール

    4. 初心者必見!独学のJava学習方法とおすすめ本、アプリを詳しく解説

      2024.01.26

      初心者必見!独学のJava学習方法とおすすめ本、アプリを詳しく解説

      #JAVA

    5. 忙しい社会人におすすめプログラミングスクール15選!失敗しない選び方も詳しく解説

      2024.01.26

      忙しい社会人におすすめプログラミングスクール15選!失敗しない選び方も詳しく解説

      #プログラミングスクール

    1. 【無料あり】大阪のおすすめプログラミングスクール14選!スクール選びのコツも紹介

      2022.01.06

      【無料あり】大阪のおすすめプログラミングスクール14選!スクール選びのコツも紹介

      #プログラミングスクール

    2. 【目的別】東京のおすすめプログラミングスクール20選!スクール選びのコツも徹底解説

      2024.01.26

      【目的別】東京のおすすめプログラミングスクール20選!スクール選びのコツも徹底解説

      #プログラミングスクール

    3. 【無料あり】福岡のおすすめプログラミングスクール13選!選び方も詳しく解説

      2024.01.26

      【無料あり】福岡のおすすめプログラミングスクール13選!選び方も詳しく解説

      #プログラミングスクール

    4. 【徹底比較】名古屋のおすすめプログラミングスクール13選!選び方も詳しく解説

      2024.01.26

      【徹底比較】名古屋のおすすめプログラミングスクール13選!選び方も詳しく解説

      #プログラミングスクール

    5. 【徹底比較】おすすめのプログラミングスクール18選!失敗しない選び方も徹底解説

      2024.01.26

      【徹底比較】おすすめのプログラミングスクール18選!失敗しない選び方も徹底解説

      #プログラミングスクール