在 PyQt 中使用 QThread 发出信号
signal with QThread in PyQt
我有一个程序需要测量 windows 中用户配置文件的大小。
我做了一个QObjectclass来测量尺寸:
class TailleRep(QObject):
size_ready = pyqtSignal(int)
def __init__(self, repertoire):
super(TailleRep, self).__init__()
self.repertoire = repertoire
def work(self):
size = self.getFolderSize(self.repertoire)
print(size)
self.size_ready.emit(size)
def getFolderSize(self, folder_path):
start_path = Path(os.path.join(folder_path, '.'))
return sum(f.stat().st_size for f in start_path.glob('**/*') if f.is_file())
console打印出来的size结果是正确的,但是当我在ui里面用这个的时候就不一样了:
import sys
import os
from PyQt5.QtCore import Qt, QObject, pyqtSignal, QThread
from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow, \
QPushButton, QVBoxLayout, QWidget
from pathlib import Path
class Window(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi()
def setupUi(self):
self.resize(300, 80)
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.sizeLabel = QLabel("Size: ---", self)
self.sizeLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
self.getSizeBtn = QPushButton("Get size", self)
self.getSizeBtn.clicked.connect(self.GetSize)
layout = QVBoxLayout()
layout.addWidget(self.sizeLabel)
layout.addWidget(self.getSizeBtn)
layout.addStretch()
self.centralWidget.setLayout(layout)
def GetSize(self):
self.getSizeBtn.setEnabled(False)
self.thread = QThread()
self.worker = TailleRep(os.getenv('USERPROFILE'))
self.worker.moveToThread(self.thread)
self.thread.started.connect(self.worker.work)
self.worker.size_ready.connect(self.size_ready)
self.thread.start()
def size_ready(self, size):
self.sizeLabel.setText("Size: {}".format(size))
self.getSizeBtn.setEnabled(True)
app = QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec())
你能告诉我我的错误在哪里吗?
问题似乎是PyQt5的一个bug,它将python整数转换为C++整数,后者最大为2147483647,由于大小大于该值而导致溢出。一种可能的解决方案是创建一个 python class 以整数作为字段,以便传递 python 对象并且没有转换。
from dataclasses import dataclass
@dataclass
class Data:
size: int
class TailleRep(QObject):
size_ready = pyqtSignal(Data)
# ...
def work(self):
ize = self.getFolderSize(self.repertoire)
print(size)
data = Data(size=size)
self.size_ready.emit(data)
def size_ready(self, data):
size = data.size
self.sizeLabel.setText("Size: {}".format(size))
self.getSizeBtn.setEnabled(True)
我有一个程序需要测量 windows 中用户配置文件的大小。
我做了一个QObjectclass来测量尺寸:
class TailleRep(QObject):
size_ready = pyqtSignal(int)
def __init__(self, repertoire):
super(TailleRep, self).__init__()
self.repertoire = repertoire
def work(self):
size = self.getFolderSize(self.repertoire)
print(size)
self.size_ready.emit(size)
def getFolderSize(self, folder_path):
start_path = Path(os.path.join(folder_path, '.'))
return sum(f.stat().st_size for f in start_path.glob('**/*') if f.is_file())
console打印出来的size结果是正确的,但是当我在ui里面用这个的时候就不一样了:
import sys
import os
from PyQt5.QtCore import Qt, QObject, pyqtSignal, QThread
from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow, \
QPushButton, QVBoxLayout, QWidget
from pathlib import Path
class Window(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi()
def setupUi(self):
self.resize(300, 80)
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.sizeLabel = QLabel("Size: ---", self)
self.sizeLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
self.getSizeBtn = QPushButton("Get size", self)
self.getSizeBtn.clicked.connect(self.GetSize)
layout = QVBoxLayout()
layout.addWidget(self.sizeLabel)
layout.addWidget(self.getSizeBtn)
layout.addStretch()
self.centralWidget.setLayout(layout)
def GetSize(self):
self.getSizeBtn.setEnabled(False)
self.thread = QThread()
self.worker = TailleRep(os.getenv('USERPROFILE'))
self.worker.moveToThread(self.thread)
self.thread.started.connect(self.worker.work)
self.worker.size_ready.connect(self.size_ready)
self.thread.start()
def size_ready(self, size):
self.sizeLabel.setText("Size: {}".format(size))
self.getSizeBtn.setEnabled(True)
app = QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec())
你能告诉我我的错误在哪里吗?
问题似乎是PyQt5的一个bug,它将python整数转换为C++整数,后者最大为2147483647,由于大小大于该值而导致溢出。一种可能的解决方案是创建一个 python class 以整数作为字段,以便传递 python 对象并且没有转换。
from dataclasses import dataclass
@dataclass
class Data:
size: int
class TailleRep(QObject):
size_ready = pyqtSignal(Data)
# ...
def work(self):
ize = self.getFolderSize(self.repertoire)
print(size)
data = Data(size=size)
self.size_ready.emit(data)
def size_ready(self, data):
size = data.size
self.sizeLabel.setText("Size: {}".format(size))
self.getSizeBtn.setEnabled(True)