Занятости с PyQt прогресс-бар
Я пытаюсь написать скрипт, который будет отображать индикатор занятости при выполнении задания. И когда задача закончена, индикатор выполнения будет заполнить до конца, показывая, что 100% задача выполнена. Я просто хочу, чтобы индикатор выполнения показывал, что задача продолжается.Но когда я начинаю задание, индикация занято останавливается.Мне кажется, что указание и задача не может продолжаться вместе. Пожалуйста, помогите мне. Вот mycode в:
from PyQt4 import QtCore, QtGui
from time import sleep
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(344, 159)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.pb = QtGui.QProgressBar(self.centralwidget)
self.pb.setGeometry(QtCore.QRect(20, 20, 301, 31))
self.pb.setProperty("value", 0)
self.pb.setObjectName(_fromUtf8("pb"))
self.btn = QtGui.QPushButton(self.centralwidget)
self.btn.setGeometry(QtCore.QRect(20, 70, 98, 27))
self.btn.setObjectName(_fromUtf8("btn"))
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 344, 25))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QObject.connect(self.btn, QtCore.SIGNAL(_fromUtf8("clicked()")), self.action)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def action(self):
self.pb.setRange(0, 0)
sleep(3) # Here I want to run a command.For example: os.system('copy something')
self.pb.setRange(0, 100)
self.pb.setValue(100)
QtGui.qApp.processEvents()
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.btn.setText(_translate("MainWindow", "Start", None))
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
4 ответов
во-первых, это плохая идея напрямую редактировать код, созданный с помощью QtDesigner. Возможно, вы видели строку # WARNING! All changes made in this file will be lost!
в верхней части документа. Для такого простого виджета вам лучше использовать ручное кодирование.
во-вторых, взгляните поближе на то, что action
гнездо на самом деле.
def action(self):
self.pb.setRange(0, 0) # Un
sleep(3) # <-- Your slot blocks HERE
self.pb.setRange(0, 100)
self.pb.setValue(100)
QtGui.qApp.processEvents()
нет причин для вашего progressBar обновлять его значение, пока ваш слот заблокирован в sleep
. Когда action
вызывается, поток слота спит в течение 3 секунд, затем устанавливает индикатор выполнения до 100.
вы не можете ожидать, что progressBar волшебным образом обновит себя во время выполнения вашей задачи. Если вы не знаете, сколько времени это займет, и вы не можете разбить его на шаги, вы должны рассмотреть возможность использования импульсные ProgressBar вместо этого (см. Пример 1 ниже). Если вы можете легко получить прогрессию своей задачи (скажем, копирование N файлов), вы должны соответствующим образом обновить значение progressBar.
в любом случае, вы должны использовать QThread
чтобы получить неблокирующее поведение, и signals
для связи между вашими потоками и вашим основным приложением.
- основное приложение запускает QThread, реализующий долгосрочную задачу.
- QThread уведомляет о прогрессии задачи (если таковая имеется) или завершении основного приложения
Пример 1 - Pulse ProgressBar:
если минимум и максимум оба установлены в 0, то прогресс бар покажет индикатор занятости вместо процента шагов.
class MyCustomWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(MyCustomWidget, self).__init__(parent)
layout = QtGui.QVBoxLayout(self)
# Create a progress bar and a button and add them to the main layout
self.progressBar = QtGui.QProgressBar(self)
self.progressBar.setRange(0,1)
layout.addWidget(self.progressBar)
button = QtGui.QPushButton("Start", self)
layout.addWidget(button)
button.clicked.connect(self.onStart)
self.myLongTask = TaskThread()
self.myLongTask.taskFinished.connect(self.onFinished)
def onStart(self):
self.progressBar.setRange(0,0)
self.myLongTask.start()
def onFinished(self):
# Stop the pulsation
self.progressBar.setRange(0,1)
class TaskThread(QtCore.QThread):
taskFinished = QtCore.pyqtSignal()
def run(self):
time.sleep(3)
self.taskFinished.emit()
Пример 2-Классический ProgressBar:
class MyCustomWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(MyCustomWidget, self).__init__(parent)
layout = QtGui.QVBoxLayout(self)
self.progressBar = QtGui.QProgressBar(self)
self.progressBar.setRange(0,100)
button = QtGui.QPushButton("Start", self)
layout.addWidget(self.progressBar)
layout.addWidget(button)
button.clicked.connect(self.onStart)
self.myLongTask = TaskThread()
self.myLongTask.notifyProgress.connect(self.onProgress)
def onStart(self):
self.myLongTask.start()
def onProgress(self, i):
self.progressBar.setValue(i)
class TaskThread(QtCore.QThread):
notifyProgress = QtCore.pyqtSignal(int)
def run(self):
for i in range(101):
self.notifyProgress.emit(i)
time.sleep(0.1)
наконец-то я получил то, что хотел, хотя немного редактирования необходимо . Я только что добавил эту строку в onFinished(): личность.прогрессбар.setValue (1) для подтверждения 100% выполнения задач. Вот код:
from PyQt4 import QtCore, QtGui
from time import sleep
import sys, os
class MyCustomWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(MyCustomWidget, self).__init__(parent)
layout = QtGui.QVBoxLayout(self)
# Create a progress bar and a button and add them to the main layout
self.progressBar = QtGui.QProgressBar(self)
self.progressBar.setRange(0,1)
layout.addWidget(self.progressBar)
button = QtGui.QPushButton("Start", self)
layout.addWidget(button)
button.clicked.connect(self.onStart)
self.myLongTask = TaskThread()
self.myLongTask.taskFinished.connect(self.onFinished)
def onStart(self):
self.progressBar.setRange(0,0)
self.myLongTask.start()
def onFinished(self):
# Stop the pulsation
self.progressBar.setRange(0,1)
self.progressBar.setValue(1)
class TaskThread(QtCore.QThread):
taskFinished = QtCore.pyqtSignal()
def run(self):
os.system('sudo apt-get install leafpad')
self.taskFinished.emit()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MyCustomWidget()
window.resize(640, 480)
window.show()
sys.exit(app.exec_())
немного поздно, но я написал подробную документацию по этому вопросу, так как многие люди, похоже, сталкиваются с этой проблемой.
применить это:
progressbar.setMinimum(0)
progressbar.setMaximum(0)
progressbar.setValue(0)
этот параметр будет иметь занятый вид, вам не нужно добавлять его в любую функцию, он может быть в конструкторе класса, если вы хотите