Python 使用QThread在PyQt5中显示QProgressDialog
我正在使用PyQt5编写一个管理销售订单的应用程序。创建订单或删除itI时,我希望显示marqee风格的进度对话框,以指示应用程序正在工作。我访问过很多帖子,其中的答案涉及到使用QThread。我尝试过实现它,但似乎遗漏了一些东西。这是我的线程课程Python 使用QThread在PyQt5中显示QProgressDialog,python,pyqt5,qthread,pyside2,qprogressdialog,Python,Pyqt5,Qthread,Pyside2,Qprogressdialog,我正在使用PyQt5编写一个管理销售订单的应用程序。创建订单或删除itI时,我希望显示marqee风格的进度对话框,以指示应用程序正在工作。我访问过很多帖子,其中的答案涉及到使用QThread。我尝试过实现它,但似乎遗漏了一些东西。这是我的线程课程 class Worker(QThread): finished = Signal() def run(self): self.x = QProgressDialog("Please wait..",None,0,
class Worker(QThread):
finished = Signal()
def run(self):
self.x = QProgressDialog("Please wait..",None,0,0)
self.x.show()
def stop(self):
self.x.close()
在主窗口的init中,我创建self.worker=worker()
现在,删除条目的代码如下所示:
msg = MsgBox("yn", "Delete Order", "Are you sure you want to delete this order?") # Wrapper for the QMessageBox
if msg == 16384:
self.worker.start() ## start the worker thread, hoping to start the progress dialog
session.delete(order) ##delete order from db
session.commit() ##commit to db
self.change_view("Active", 8) ##func. clean up the table.
self.worker.finished.emit() ##emit the finished signal to close the progress dialog
结果是没有显示任何进度对话框。gui只是冻结一两秒钟,然后条目删除,没有显示任何进度对话框
很抱歉,我的代码太长,所以我无法在这里全部包含,我只是想看看是否有严重错误。您的代码有两个主要问题:
class Worker(QThread):
def __init__(self, session, order):
super.__init__()
self.session = session
self.order = order
def run(self):
self.session.delete(self.order)
self.session.commit()
class Whatever(QMainWindow):
def __init__(self):
super().__init__()
# ...
self.progressDialog = QProgressDialog("Please wait..", None, 0, 0, self)
def deleteOrder(self, session, order):
msg = MsgBox("yn", "Delete Order",
"Are you sure you want to delete this order?")
if msg == MsgBox.Yes: # you should prefer QMessageBox flags
self.worker = Worker(session, order)
self.worker.started(self.progressDialog.show())
self.worker.finished(self.deleteCompleted)
self.worker.start()
def deleteCompleted(self):
self.progressDialog.hide()
self.change_view("Active", 8)
class Worker(QThread):
def __init__(self, session, order):
super.__init__()
self.session = session
self.order = order
def run(self):
self.session.delete(self.order)
self.session.commit()
class Whatever(QMainWindow):
def __init__(self):
super().__init__()
# ...
self.progressDialog = QProgressDialog("Please wait..", None, 0, 0, self)
def deleteOrder(self, session, order):
msg = MsgBox("yn", "Delete Order",
"Are you sure you want to delete this order?")
if msg == MsgBox.Yes: # you should prefer QMessageBox flags
self.worker = Worker(session, order)
self.worker.started(self.progressDialog.show())
self.worker.finished(self.deleteCompleted)
self.worker.start()
def deleteCompleted(self):
self.progressDialog.hide()
self.change_view("Active", 8)
由于处理过程中“进度”对话框应保持打开状态,因此还应防止用户关闭它。为此,您可以在其上安装事件过滤器,并确保接受任何关闭事件;此外,由于QProgressDialog继承自QDialog,因此应过滤掉Esc键,否则它不会关闭对话框,而是会拒绝并隐藏它
class Whatever(QMainWindow):
def __init__(self):
super().__init__()
# ...
self.progressDialog = QProgressDialog("Please wait..", None, 0, 0, self)
self.progressDialog.installEventFilter(self)
def eventFilter(self, source, event):
if source == self.progressDialog:
# check for both the CloseEvent *and* the escape key press
if event.type() == QEvent.Close or event == QKeySequence.Cancel:
event.accept()
return True
return super().eventFilter(source, event)
需要注意的是,与您经历的冻结无关,您永远不会使用类似于
self.x.setValue(progress)
的内容更新进度条。这是因为我只希望它在db更新完成之前给出忙碌指示。这是一个选框样式的条,所以最小值和最大值都设置为零。哦,好的。然后我认为解决方案在于两件事中的一件:1-你需要保持对进度对话框的引用“活动”并存储在self
中,我指的是来自你的程序界面的self
,而不是来自你的类。或2-进度对话框需要有一个父级,它是您的程序界面。在这两种情况下,您都需要找到一种方法将self作为参数传递给QThread(称之为zelf
或其他什么)。请提供一个示例,您应该将删除订单的操作发送给线程,不是QDialog的创建。该对话框应该在主线程上创建,并使用QThread.started
和QThread.finished
信号显示/隐藏。这对理解线程非常有帮助。然而,遵循这一理念意味着我必须为每个处理数据库的函数创建线程。因此,最终主窗口功能将被划分为不同的独立线程。这是一个好的实践吗?任何可能阻塞的操作通常都会移动到单独的线程。请注意,您应该尝试优化它们的使用,避免不必要的创建(您可以重用线程,每次只需正确设置它)。另外,请查看QRunnable和QThreadPool。