PyQtの基礎 - 画面

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
2020年10月2日 (金) 11:58時点におけるWiki (トーク | 投稿記録)による版 (→‎レイアウト)
ナビゲーションに移動 検索に移動

概要



画面の表示

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

 # - * - 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()



ステータスバーの表示

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

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

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

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


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

 # - * - 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()


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

 # - * - 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()


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

 timer = QTimer(self)
 timer.timeout.connect(self.getDateTime)
 timer.start(1000)



メニューバーの表示

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

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

 # - * - 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()



レイアウト

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関数により、チェックを入力するたびにチェックボックスが追加される現象を防いでいる。

 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_())


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

 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_())