【发布时间】:2021-02-08 09:29:17
【问题描述】:
首先,我目前正在将我的源代码从 PyQt5 迁移到 PySide2,这需要我更改一些语法。正如site 所说,从 PyQt 迁移到 Pyside2 只需要做 3 件事。
1.app.exec_。 exec_ 被用作 exec 是 Python2 关键字。 Python3下,PyQt5允许使用exec,但不允许使用PySide2。
2.PyQt5下是QtCore.pyqtSignal和QtCore.pyqtSlot,PySide2下是QtCore.Signal和QtCore.Slot。
3.加载UI文件。
但无论如何,后来当我尝试运行我的代码时,它给了我以下错误:
QThread:在线程仍在运行时销毁
我有超过 2000 行代码,除了我最后一次尝试调用 QFileDialog 的操作之外,我无法确定这是什么原因,这应该不是问题(我已经用 PyQt 对此进行了测试导入,没有问题,也没有任何警告)。但在 PySide2 中,它肯定是它的原因。我查看this,他没有和我一样的问题。我不想从不同的线程调用 QFileDialog。
这是我在 PyQt5 中工作代码的最小可重现示例:
import sys
import os
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QFileDialog, QMessageBox, QWidget, QDialog
import random
class MyWidget(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.path = os.path.abspath(os.path.dirname(sys.argv[0]))
self.button = QtWidgets.QPushButton("Open File")
self.labelFile = QtWidgets.QLabel("empty")
self.labelData = QtWidgets.QLabel("None")
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.button)
self.layout.addWidget(self.labelFile)
self.layout.addWidget(self.labelData)
self.setLayout(self.layout)
self.button.clicked.connect(self.open_file)
timer = QtCore.QTimer(self)
timer.timeout.connect(self.update_data_value)
timer.start(1000)
def open_file(self):
x = QFileDialog.getOpenFileName(self,"Pilih File CSV yang Ingin Diproses",self.path,"CSV Files (*.csv)")
self.labelFile.setText(x[0])
def update_data_value(self):
self.DataProcess = DataProcess()
self.DataProcess.progress.connect(self.update_data_label)
self.DataProcess.start()
def update_data_label(self,x):
self.labelData.setText(str(x[0]))
class DataProcess(QtCore.QThread):
progress = QtCore.pyqtSignal(object)
def __init__(self):
QtCore.QThread.__init__(self)
def run(self):
x = random.randint(1,100)
self.progress.emit([str(x)+ " from thread"])
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
widget = MyWidget()
widget.show()
sys.exit(app.exec_())
在将导入重命名为 PySide2 并将“pyqtsignal”重命名为“Signal”之后,这是 PySide2 中的非工作项
import sys
import os
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtWidgets import QMainWindow, QFileDialog, QMessageBox, QWidget, QDialog
import random
class MyWidget(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.path = os.path.abspath(os.path.dirname(sys.argv[0]))
self.button = QtWidgets.QPushButton("Open File")
self.labelFile = QtWidgets.QLabel("empty")
self.labelData = QtWidgets.QLabel("None")
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.button)
self.layout.addWidget(self.labelFile)
self.layout.addWidget(self.labelData)
self.setLayout(self.layout)
self.button.clicked.connect(self.open_file)
timer = QtCore.QTimer(self)
timer.timeout.connect(self.update_data_value)
timer.start(1000)
def open_file(self):
x = QFileDialog.getOpenFileName(self,"Pilih File CSV yang Ingin Diproses",self.path,"CSV Files (*.csv)")
self.labelFile.setText(x[0])
def update_data_value(self):
self.DataProcess = DataProcess()
self.DataProcess.progress.connect(self.update_data_label)
self.DataProcess.start()
def update_data_label(self,x):
self.labelData.setText(str(x[0]))
class DataProcess(QtCore.QThread):
progress = QtCore.Signal(object)
def __init__(self):
QtCore.QThread.__init__(self)
def run(self):
x = random.randint(1,100)
self.progress.emit([str(x)+ " from thread"])
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
widget = MyWidget()
widget.show()
sys.exit(app.exec_())
所以在创建了这个最小示例之后,我意识到 PySide QFileDialog 使 QThread 停止,而 PyQt QFileDialog 不会冻结主线程。在类似的语法架构中我能做些什么来处理这个问题? (例如不使用“movetothread”或“QObject”)
【问题讨论】:
-
这个解决方案 stackoverflow.com/questions/31983412/… 使用 nativedialog 也不适合我
-
每隔一秒连续创建一个DataProcess实例有什么意义?
-
正如我所提到的。它是一个最小的可重现示例。我在我的真实世界应用程序中嵌入了手表和数据库状态,每 1 秒更新一次。该问题仅存在于 pyside2 中,而不存在于 pyqt5 中。我还不想被许可绑定。我还是新手
-
@musicamante 我还在这里阅读了您回答的问题stackoverflow.com/questions/63177758/…。我已经尝试过了,但我仍然没有运气。抱歉英语是我的第二语言
-
对不起,但这并不能真正回答问题。如果您需要每 1 秒执行一次耗时的任务,请使用
time.sleep或更好的self.sleep(使用 QThread 函数)。我不使用 pyside,我无法重现您的问题,但我会从那开始。如果您需要控制任务的重复是否应该实际发生,则将 pythonQueue()对象添加到其__init__内的线程实例中,并在每次循环在while True循环中重复时检查它。
标签: python-3.x pyqt5 qthread pyside2