PyQtの基礎 - 画面

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
2021年11月18日 (木) 09:21時点におけるWiki (トーク | 投稿記録)による版 (文字列「<source」を「<syntaxhighlight」に置換)
ナビゲーションに移動 検索に移動

概要



画面の表示

まず、PyQtで基本となるものは、画面を表示することである。
以下のサンプルコードでは、QWidgetクラスを使用して画面のみを表示している。

<syntaxhighlight lang="python">
# - * - coding: utf8 - * -

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

# QWidgetクラスの使用
class MyWindow(QWidget):

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

       self.title  = "ウィンドウのタイトル"
       self.width  = 500
       self.height = 400
       self.setWindowTitle(self.title)
       self.setGeometry(0, 0, self.width, self.height)

       self.show()


def main():
   App = QApplication(sys.argv)
   Window = MyWindow()
   sys.exit(App.exec_())


if __name__ == "__main__":
   main()
</source>



ステータスバーの表示

ここでは、画面にステータスバーを表示する方法を記載する。
ステータスバーには、現在の画面内の情報等を表示することが可能である。

上記のセクションでは、QWidgetクラスを継承したMyWindowクラスを作成して画面を表示しているが、
ステータスバーを表示するには、QMainWindowクラスを継承して画面を作成する必要がある。

QWidgetクラスやQDialogクラスを使用して画面を作成することもできるが、
メイン画面においてはQMainWindowクラスを使用することを推奨する。
それは、QMainWindowクラスは、以下に示すメイン画面を作成するための機能を提供しているからである。

  • メニューバー
  • ツールバー
  • ドックウィジェット
  • 中央ウィジェット
  • ステータスバー


以下のサンプルコードでは、ステータスバーを表示している。

<syntaxhighlight lang="python">
# - * - coding: utf8 - * -

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

# QMainWindowクラスの使用
class MyWindow(QMainWindow):

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

       self.title  = "ウィンドウのタイトル"
       self.width  = 500
       self.height = 400
       self.setWindowTitle(self.title)
       self.setGeometry(0, 0, self.width, self.height)
       self.statusBar().showMessage('ステータスバーの表示')
       self.show()


def main():
   App = QApplication(sys.argv)
   Window = MyWindow()
   sys.exit(App.exec_())


if __name__ == "__main__":
   main()
</source>


以下のサンプルコードでは、ステータスバーにデジタル時計を表示している。

<syntaxhighlight lang="python">
# - * - coding: utf8 - * -

import sys
import datetime  # 時計を表示するために必要

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# QMainWindowクラスの使用
class MyWindow(QMainWindow):

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

       self.title  = "ウィンドウのタイトル"
       self.width  = 500
       self.height = 400
       self.setWindowTitle(self.title)
       self.setGeometry(0, 0, self.width, self.height)
       self.show()

       timer = QTimer(self)
       timer.timeout.connect(self.getDateTime)
       timer.start(1000)  # 1000ミリ秒


    def getDateTime(self):
       dt     = datetime.datetime.today()
       dt_str = dt.strftime("%Y年%m月%d日 %H時%M分%S秒")
       self.statusBar().showMessage("ステータスバーの時計" + " " + dt_str)


def main():
   App = QApplication(sys.argv)
   Window = MyWindow()
   sys.exit(App.exec_())


if __name__ == "__main__":
   main()
</source>


上記のサンプルコードでは、シグナルとスロットと呼ばれる機能を使用している。
オブジェクトは、何らかのイベントが生じた際にシグナルを発生させて、それをスロットの関数が受け取ることで画面上の情報を更新することができる。
ここでは、QTimerのインスタンスを生成した後、timeoutシグナルに対してgetDateTimeメソッドをスロットとして呼び出して、それらをconnectで結び付けている。

<syntaxhighlight lang="python">
timer = QTimer(self)
timer.timeout.connect(self.getDateTime)
timer.start(1000)
</source>



メニューバーの表示

このセクションでは、メニューバーを表示する。

以下のサンプルコードでは、メニューバーと[ファイル]メニューおよび[終了]サブメニューを表示して、
[終了]サブメニューにソフトウェアを終了するメニューバーアクションを定義している。

<syntaxhighlight lang="python">
# - * - coding: utf8 - * -

import sys

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# QMainWindowクラスの使用
class MyWindow(QMainWindow):

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

       self.title  = "ウィンドウのタイトル"
       self.width  = 500
       self.height = 400

       # メニューバーの定義
       exitAction = QAction('&終了', self)
       exitAction.setShortcut('Ctrl+Q')
       exitAction.setStatusTip('終了する')
       exitAction.triggered.connect(qApp.quit)

       # メニューバーアクションの追加
       menubar = self.menuBar()
       fileMenu = menubar.addMenu('&ファイル')
       fileMenu.addAction(exitAction)

       self.setWindowTitle(self.title)
       self.setGeometry(0, 0, self.width, self.height)

       # ステータスバー
       self.statusBar()

 

       self.show()


def main():
   App = QApplication(sys.argv)
   Window = MyWindow()
   sys.exit(App.exec_())


if __name__ == "__main__":
   main()
</source>



レイアウト

PyQtのレイアウトは、QHBoxとQVBoxの2種類(縦(horizon)と横(vertical))が存在する。
指定が無い場合、QHBox(縦のレイアウト)が自動的に配置される。

以下のサンプルコードにおいて、13行目のself.upper.stateChanged.connect(self.uppercase)では、
connectにより、"Upper"チェックボックスにチェックが入っている時、uppercase関数にコネクトする。

addWiget関数では、upper_aチェックボックスとupper_bチェックボックスを指定している。
また、addWiget関数では、verticalを指定している。

verticalにはQVBoxLayout(縦のレイアウト)を指定しているので、チェックボックスが縦に並ぶ。
グループ化されていないので、複数のチェックボックスを選択することができる。

36行目において、チェックボックスにチェックが入力されていない時は、
removeWiget関数により、チェックを入力するたびにチェックボックスが追加される現象を防いでいる。

<syntaxhighlight lang="python">
import sys
import sip

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *


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

      # 上のチェックボックス
      self.upper = QCheckBox('Upper', self)
      self.upper.move(100, 30)
      self.upper.stateChanged.connect(self.uppercase)

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

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

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


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

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


if __name__ == '__main__':
   App = QApplication(sys.argv)
   Window = MainWindow()
   Window.show()
   sys.exit(App.exec_())
</source>


以下のサンプルコードでは、QPushButtonを追加して、ボタンの押下時のイベントをoutput関数にコネクトしている。
output関数では、各チェックボックスにチェックが入力されている時、それぞれ文字Aと文字Bをコンソールに出力している。

<syntaxhighlight lang="python">
import sys
import sip

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *


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

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

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

      # ボタンの追加
      self.button = QPushButton('コンソールに出力', self)
      self.button.clicked.connect(self.output)

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

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


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

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


   def output(self):
      outputs = []

      if(self.upper_a.isChecked()):
         outputs.append("A")
      if(self.upper_b.isChecked()):
         outputs.append("B")

      for output in outputs:
         print(output)


if __name__ == '__main__':
   App = QApplication(sys.argv)
   Window = MainWindow()
   Window.show()
   sys.exit(App.exec_())
</source>