self.dialogBox.close()
self.state = "processing"
self.__clearLayout(self.layout)
print(1)
self.controller.process()
我正在运行以下代码。该对话框是一个PyQt对话框,self.state
只是一个当前状态,self.__clearLayout
清除PyQt小部件的当前布局,print(1)
用于调试目的,self.controller.process()
处理事情是什么,需要一段时间。我的目标是清除UI,然后让我的程序进程,但它是乱序。它打印1
并开始处理,这告诉我它是有序的,但UI直到完成该过程后才设置。有关如何解决此问题的任何提示?
def processUi(self):
self.dialogBox.close()
self.state = "processing"
self.__clearLayout(self.layout)
#label
processingLabel = QtWidgets.QLabel()
processingLabel.setMaximumSize(500, 500)
processingLabel.setFont(QtGui.QFont("Mono", 16))
processingLabel.setText("Processing...may take a few minutes.")
#set the current layout
currentLayout = QtWidgets.QVBoxLayout()
currentLayout.setContentsMargins(0,0,0,0)
currentLayout.addStretch()
currentLayout.addWidget(processingLabel)
currentLayout.addStretch()
self.layout.addStretch()
self.layout.addLayout(currentLayout)
self.layout.addStretch()
#thread for processing
processing = multiprocessing.Process(target=self.controller.process, args=())
processing.start()
processing.join()
self.finishedUi()
这是完整的代码。目标是在处理工作时设置您看到的ui代码,并在处理完成后调用finishedUi。
答案 0 :(得分:0)
我假设您的清晰布局方法与我在this answer中提供的方法相同。
如果是这样,问题出在deleteLater
,这会延迟删除,直到控制权返回到事件循环。无法强制处理延迟删除事件(例如QApplication.processEvents()
将无效)。相反,有必要使用sip module直接删除小部件:
import sip
def clearLayout(self, layout):
if layout is not None:
while layout.count():
item = layout.takeAt(0)
widget = item.widget()
if widget is not None:
sip.delete(widget)
else:
self.clearLayout(item.layout())
如果使用多线程,则无需担心sip.delete
,因为线程启动后将立即处理任何挂起的删除事件。下面是一个简单的演示,演示了如何使用线程进行非阻塞处理:
from PyQt5 import QtCore, QtWidgets
class Worker(QtCore.QThread):
progressChanged = QtCore.pyqtSignal(int)
def run(self):
for tick in range(10):
self.msleep(500)
self.progressChanged.emit(tick + 1)
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.button = QtWidgets.QPushButton('Start', self)
self.button.clicked.connect(self.handleButton)
self.frame = QtWidgets.QFrame(self)
self.frame.setMinimumHeight(100)
self.frame.setLayout(QtWidgets.QVBoxLayout())
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.frame)
layout.addWidget(self.button)
def handleButton(self):
self.button.setEnabled(False)
self.clearLayout(self.frame.layout())
label = QtWidgets.QLabel('Starting')
self.frame.layout().addWidget(label)
def progress(tick):
label.setText('Processing... Count = %d' % tick)
def finish():
label.setText('Finished')
self.button.setEnabled(True)
thread.deleteLater()
thread = Worker(self)
thread.finished.connect(finish)
thread.progressChanged.connect(progress)
thread.start()
def clearLayout(self, layout):
if layout is not None:
while layout.count():
item = layout.takeAt(0)
widget = item.widget()
if widget is not None:
widget.deleteLater()
else:
self.clearLayout(item.layout())
if __name__ == '__main__':
app = QtWidgets.QApplication(['test'])
window = Window()
window.setGeometry(600, 100, 300, 200)
window.show()
app.exec_()