PySide (Qt for Python) は、Qt(キュート)の Python バインディングで、GUI などを構築するためのクロスプラットフォームなライブラリです。配布ライセンスは LGPL で公開されています。最新のバージョンは Qt6 に対応した PySide6(記事執筆時点で 6.2.2.1)です。
大きなファイルを読み込むときや、時間がかかる処理をしている時、GUI が反応しなくなります。自分用にちゃちゃっと作る GUI プログラムではそれでも我慢できますが、他の人も利用するようになったら、ちとダサいです。プログラムが固まると苦情を受けること必至です。ひと手間かけてスレッドで処理を分ければいいのですが、結局のところ、処理が終わるまでは他の処理をできなくして、進捗だけ表示させておけば良い場合が多いです。
そんなとき、QProgressDialog を利用すれば、進捗ダイアログで表示させ modal にしておけば、進捗を表示する上、親ウィンドウの操作ができなくなって便利です。
本記事では、下記の OS 環境を使用しています。
![]() |
Fedora Linux 35 Workstation | x86_64 |
まずは、ボタンをクリックしてダミーのタスクを実行し、その進捗を表示させるサンプルです。
qt_progressdialog.py の実行例
qt_progressdialog.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# coding: utf-8 | |
import sys | |
import time | |
from PySide6.QtWidgets import ( | |
QApplication, | |
QMainWindow, | |
QProgressDialog, | |
QPushButton, | |
) | |
from PySide6.QtCore import ( | |
QThread, | |
Signal, Qt, | |
) | |
class Example(QMainWindow): | |
def __init__(self, parent=None): | |
super().__init__(parent) | |
self.init_ui() | |
self.setWindowTitle('ProgressDialog & Thread') | |
self.resize(300, 100) | |
def init_ui(self): | |
but = QPushButton('START') | |
but.clicked.connect(self.task_start) | |
self.setCentralWidget(but) | |
def task_start(self): | |
button = self.sender() | |
button.setEnabled(False) | |
progress = QProgressDialog(labelText='Working...', parent=self) | |
progress.setWindowModality(Qt.WindowModal) | |
progress.setCancelButton(None) | |
progress.setWindowTitle('status') | |
progress.show() | |
task = TaskThread(self) | |
task.progressChanged.connect(progress.setValue) | |
task.start() | |
task.progressCompleted.connect(lambda: self.task_end(button, progress)) | |
def task_end(self, button, progress): | |
button.setEnabled(True) | |
progress.cancel() | |
class TaskThread(QThread): | |
progressChanged = Signal(int) | |
progressCompleted = Signal() | |
def run(self): | |
for progress in range(0, 101): | |
time.sleep(0.1) | |
self.progressChanged.emit(progress) | |
time.sleep(0.5) | |
self.progressCompleted.emit() | |
self.progressChanged.emit(0) | |
self.exit(0) | |
def main(): | |
app = QApplication(sys.argv) | |
ex = Example() | |
ex.show() | |
sys.exit(app.exec()) | |
if __name__ == '__main__': | |
main() |
一方、進捗を測る数字を取れない場合もあります。そんなときは、QProgressDialog の setRange メソッドで (0, 0) としておけば、進捗に関係なく進捗バーが動いているようになります。
qt_progressdialog_2.py の実行例
qt_progressdialog_2.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# coding: utf-8 | |
import sys | |
import time | |
from PySide6.QtWidgets import ( | |
QApplication, | |
QMainWindow, | |
QProgressDialog, | |
QPushButton, | |
) | |
from PySide6.QtCore import ( | |
QThread, | |
Signal, Qt, | |
) | |
class Example(QMainWindow): | |
def __init__(self, parent=None): | |
super().__init__(parent) | |
self.init_ui() | |
self.setWindowTitle('ProgressDialog & Thread (2)') | |
self.resize(300, 100) | |
def init_ui(self): | |
but = QPushButton('START') | |
but.clicked.connect(self.task_start) | |
self.setCentralWidget(but) | |
def task_start(self, button): | |
button = self.sender() | |
button.setEnabled(False) | |
progress = QProgressDialog(labelText='Working...', parent=self) | |
progress.setWindowModality(Qt.WindowModal) | |
progress.setCancelButton(None) | |
progress.setRange(0, 0) | |
progress.setWindowTitle('status') | |
progress.show() | |
task = TaskThread(self) | |
task.start() | |
task.progressCompleted.connect(lambda: self.task_end(button, progress)) | |
def task_end(self, button, progress): | |
button.setEnabled(True) | |
progress.cancel() | |
class TaskThread(QThread): | |
progressCompleted = Signal() | |
def run(self): | |
for progress in range(0, 101): | |
time.sleep(0.1) | |
time.sleep(0.5) | |
self.progressCompleted.emit() | |
self.exit(0) | |
def main(): | |
app = QApplication(sys.argv) | |
ex = Example() | |
ex.show() | |
sys.exit(app.exec()) | |
if __name__ == '__main__': | |
main() |
QProgressDialog のダイアログ画面では、デフォルトでキャンセルボタンが表示されます。今回は良いサンプルを用意できなかったので、表示しないようにしてしまいましたが、サンプルを工夫できれば、あらためて紹介します。
参考サイト

にほんブログ村
0 件のコメント:
コメントを投稿