pyqt5
プログレスバーの紹介
サーチ…
前書き
プログレスバーは、ユーザーエクスペリエンスの不可欠な部分であり、ユーザーがGUI上で実行される特定のプロセスの残り時間に関するアイデアを得るのに役立ちます。このトピックでは、独自のアプリケーションでプログレスバーを実装するための基本について説明します。
このトピックでは、QThreadと新しいシグナル/スロットメカニズムについて軽く触れる予定です。 PyQt5ウィジェットの基本的な知識も読者に期待されます。
例を追加するときは、PyQt5とPythonの組み込み関数を使って機能を実演するだけです。
PyQt5のみ
備考
これらの例を試してみることは、学習を始める最良の方法です。
基本的なPyQtプログレスバー
これは非常に基本的なプログレスバーであり、最低限必要なものだけを使用します。
この全体の例を最後まで読むことが賢明でしょう。
import sys
import time
from PyQt5.QtWidgets import (QApplication, QDialog,
QProgressBar, QPushButton)
TIME_LIMIT = 100
class Actions(QDialog):
"""
Simple dialog that consists of a Progress Bar and a Button.
Clicking on the button results in the start of a timer and
updates the progress bar.
"""
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('Progress Bar')
self.progress = QProgressBar(self)
self.progress.setGeometry(0, 0, 300, 25)
self.progress.setMaximum(100)
self.button = QPushButton('Start', self)
self.button.move(0, 30)
self.show()
self.button.clicked.connect(self.onButtonClick)
def onButtonClick(self):
count = 0
while count < TIME_LIMIT:
count += 1
time.sleep(1)
self.progress.setValue(count)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Actions()
sys.exit(app.exec_())
プログレスバーは最初にfrom PyQt5.QtWidgets import QProgressBar
その後、 QtWidgets
他のウィジェットと同じように初期化されQtWidgets
line self.progress.setGeometry(0, 0, 300, 25)
メソッドは、ダイアログ上のx,y
位置、および進行状況バーの幅と高さを定義します。
我々は次に、ボタンを使って移動.move()
によって30px
のギャップが存在するであろう下方ように5px
2つのウィジェットの間です。
ここで、 self.progress.setValue(count)
は進捗を更新するために使用されます。 .setMaximum()
を使用して最大値を設定すると、自動的に値が計算されます。たとえば、最大値が50に設定されている場合、 TIME_LIMIT
は100であるため、1 TIME_LIMIT
ではなくTIME_LIMIT
%にホップします。また、 .setMinimum()
を使用して最小値を設定して、進行状況バーを特定の値から開始させることもできます。
このプログラムを実行すると、これに類似したGUIが生成されます。
ご覧のとおり、GUIはTIME_LIMIT
条件を満たしていないTIME_LIMIT
、フリーズして応答しなくTIME_LIMIT
ます。これは、 time.sleep
が、OSにプログラムが無限ループに陥っていると信じさせるためtime.sleep
。
QThread
だから私たちはこの問題をどのように克服するのですか? PyQt5が提供するスレッドクラスを使用できます。
import sys
import time
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import (QApplication, QDialog,
QProgressBar, QPushButton)
TIME_LIMIT = 100
class External(QThread):
"""
Runs a counter thread.
"""
countChanged = pyqtSignal(int)
def run(self):
count = 0
while count < TIME_LIMIT:
count +=1
time.sleep(1)
self.countChanged.emit(count)
class Actions(QDialog):
"""
Simple dialog that consists of a Progress Bar and a Button.
Clicking on the button results in the start of a timer and
updates the progress bar.
"""
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('Progress Bar')
self.progress = QProgressBar(self)
self.progress.setGeometry(0, 0, 300, 25)
self.progress.setMaximum(100)
self.button = QPushButton('Start', self)
self.button.move(0, 30)
self.show()
self.button.clicked.connect(self.onButtonClick)
def onButtonClick(self):
self.calc = External()
self.calc.countChanged.connect(self.onCountChanged)
self.calc.start()
def onCountChanged(self, value):
self.progress.setValue(value)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Actions()
sys.exit(app.exec_())
これらの変更を分解しましょう。
from PyQt5.QtCore import QThread, pyqtSignal
この行はPyQt5
実装であるQthread
をインポートして、バックグラウンドでプログラムのいくつかの部分(関数やクラスなど)を分割して実行します(マルチスレッドとも呼ばれます)。これらの部分はスレッドとも呼ばれます。デフォルトでは、すべてのPyQt5
プログラムはメインスレッドを持ち、他のスレッド(ワーカースレッド)は、メインプログラムを機能させたまま、余分な時間がかかり、処理が集中するタスクをバックグラウンドにオフロードするために使用されます。
2番目のインポートpyqtSignal
は、ワーカーとメインスレッド間でデータ(シグナル)を送信するために使用されます。この例では、メインスレッドにプログレスバーを更新するように指示するために使用します。
これで、カウンタのwhileループをExternal
という別のクラスに移動しました。
class External(QThread):
"""
Runs a counter thread.
"""
countChanged = pyqtSignal(int)
def run(self):
count = 0
while count < TIME_LIMIT:
count +=1
time.sleep(1)
self.countChanged.emit(count)
QThread
をサブクラス化することで、 External
を基本的に別のスレッドで実行できるクラスに変換します。スレッドは、いつでもそのスレッドの利点を追加して開始または停止することができます。
ここでcountChanged
現在進行中であり、 pyqtSignal(int)
タイプのもので送信される信号ワーカースレッド指示int
。一方、 self.countChanged.emit(count)
は、メインスレッド内の任意の接続にシグナルを送信するだけです(通常、他のワーカースレッドと通信するためにも使用できます)。
def onButtonClick(self):
self.calc = External()
self.calc.countChanged.connect(self.onCountChanged)
self.calc.start()
def onCountChanged(self, value):
self.progress.setValue(value)
ボタンをクリックすると、 self.onButtonClick
が実行され、スレッドも開始されます。スレッドは.start()
開始されます。前に作成したself.calc.countChanged
を、プログレスバー値を更新するために使用したメソッドに接続したことにも注意してください。 External::run::count
が更新されるたびに、 int
値もonCountChanged
送られonCountChanged
。
これは、これらの変更を行った後のGUIの見方です。
それはまた、はるかに反応し、凍結することはありません感じる必要があります。