我正在设计一个编辑DICOM的程序。具体来说,我遇到了与PyQt UI正确交互的问题。
我希望能够点击“暂停”和“停止”按钮来暂停或停止我的编辑功能。我的编辑功能需要花费大量时间来处理/循环。根据正在编辑的文件数量,可能需要30秒到一个多小时。因此,我决定使用Qt的本机线程功能将我的编辑功能放入自己的线程中。我能够让线程工作,即:从我的MainWindow类中,我可以单击一个初始化我的编辑类的按钮(类编辑(QThread)),但是与GUI的交互仍然会崩溃程序,我不知道为什么!下面我添加了我正在使用的一般代码结构/设置的示例。
class anonymizeThread(QThread):
def __init__(self):
QThread.__init__(self)
def __del__(self):
self.wait()
#def sendAnon(self, progress_val):
# self.completed = 0
# return self.completed
def run(self):
# while self.completed < 100:
# self.completed += 0.00001
# self.emit(QtCore.SIGNAL('PROGRESS'), self.completed)
# ANONYMIZE FUNCTION!
i = 0
#flag = self.stop_flag
while i < 10000000: # and self.stop_flag is not 1:
print(i)
i+=1
print('i didnt enter the loop')
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
# connect the buttons
self.worker = anonymizeThread()
self.anonbtn.clicked.connect(self.anonymize)
self.open_directory.clicked.connect(self.open_dir)
self.pause.clicked.connect(self.paused)
self.stopbtn.clicked.connect(self.stopped)
# block button signals to start
self.pause.blockSignals(True)
self.stopbtn.blockSignals(True)
self.dir_name = None
self.pause_flag = None
self.stop_flag = None
self.anon_flag = None
# This is how we quit from the main menu "File" option
extractAction = self.actionQuit_Ctrl_Q
extractAction.setShortcut("Ctrl+Q")
extractAction.setStatusTip('Leave The App')
extractAction.triggered.connect(self.close_application)
def updateProgressBar(self,val):
self.progressBar.setValue(val)
def close_application(self):
choice = QMessageBox.question(self, 'Just had to check...', "Are you sure you want to exit?", QMessageBox.Yes | QMessageBox.No)
if choice == QMessageBox.Yes:
sys.exit()
else:
pass
def anonymize(self):
self.pause.blockSignals(False)
self.stopbtn.blockSignals(False)
self.worker.start()
# check if directory chosen
# self.progressBar.setMaximum(len(dcm)
# start our anon thread!
def paused(self):
#only if running
if self.pause_flag is 0:
self.pause_flag = 1
self.pause.setText('Start')
elif self.pause_flag is 1:
self.pause_flag = 0
self.pause.setText('Pause')
else:
pass
def stopped(self): # need a self.stop() for anonThread
choice = QMessageBox.question(self,'Stop', "Are you sure you want to stop? You will not be able to pick up exactly where you left off.",
QMessageBox.Yes | QMessageBox.No)
if choice == QMessageBox.Yes:
self.stop_flag = 1
#self.stopbtn.blockSignals(True)
#self.paused.blockSignals(True)
else:
pass
def open_dir(self):
self.dir_name = str(QFileDialog.getExistingDirectory(self, "Select Directory"))
if len(self.dir_name) is not 0:
self.anon_flag = 0
def main():
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
答案 0 :(得分:0)
感谢@eyllansec和@ekhumoro ..
在上面的代码中,self.stop_flag = ...
的所有实例都应该是self.worker.stop_flag = ...
,因为它正在更改要在worker类/线程中使用的变量。我的错误是假设两个类继承了相同的“自我”。
如果有其他错误或更好地解释我做错了什么,请发一个答案,我会接受它!
答案 1 :(得分:0)
建议不要直接访问标志,最好通过函数来透明地使用它,因为同一个类应该验证任务。
还可以给出一个小延迟,以便应用程序可以处理图形部分,另一个可能的改进是避免使用sys.exit,你可以调用关闭窗口的close方法。
在下面的代码中,我实现了stop和pause方法。
class anonymizeThread(QThread):
def __init__(self):
QThread.__init__(self)
self.onRunning = True
self.onStop = False
def __del__(self):
self.wait()
def stop(self):
self.onStop = True
def pause(self):
if self.isRunning():
self.onRunning = not self.onRunning
def run(self):
i = 0
#flag = self.stop_flag
while i < 10000000:
if self.onRunning: # and self.stop_flag is not 1:
print(i)
i+=1
if self.onStop:
break
QThread.msleep(10)
print('i didnt enter the loop')
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
# connect the buttons
self.worker = anonymizeThread()
self.anonbtn.clicked.connect(self.anonymize)
self.pause.clicked.connect(self.paused)
self.stopbtn.clicked.connect(self.stopped)
# block button signals to start
self.pause.blockSignals(True)
self.stopbtn.blockSignals(True)
def close_application(self):
choice = QMessageBox.question(self, 'Just had to check...', "Are you sure you want to exit?", QMessageBox.Yes | QMessageBox.No)
if choice == QMessageBox.Yes:
self.close()
def anonymize(self):
self.pause.blockSignals(False)
self.stopbtn.blockSignals(False)
self.worker.start()
def paused(self):
self.worker.pause()
def stopped(self): # need a self.stop() for anonThread
choice = QMessageBox.question(self,'Stop', "Are you sure you want to stop? You will not be able to pick up exactly where you left off.",
QMessageBox.Yes | QMessageBox.No)
if choice == QMessageBox.Yes:
self.worker.stop()