最近闲的没事写了个漫画爬虫,但在下载的时候出现了问题,有些漫画100多章还好,有的3000章,这就需要连续创建3000个组件,而在创建组件时会直接卡死主界面。
提供两种解决方法。
1. 多线程
将循环放到其他线程,不在同一个时间点创建
python
from PySide6.QtWidgets import QScrollArea, QWidget, QGridLayout, QLabel, QApplication
from collections import deque
from PySide6.QtCore import QThread, Signal
class ListLoadThread(QThread):
signal = Signal(object, object) # 函数,参数
def __init__(self, parent=None):
super().__init__(parent)
self.queue = deque()
self.signal.connect(self._handle_callback)
def _handle_callback(self, func, item):
if func:
func(item)
def run(self):
while self.queue:
items, func = self.queue.popleft()
for item in items:
self.msleep(30)
self.signal.emit(func, item)
def addItem(self, items: list, func: object):
self.queue.append((items, func))
if not self.isRunning():
self.start()
class ScrollArea(QScrollArea):
def __init__(self, parent=None):
super().__init__(parent)
self.scrollWidget = QWidget()
self.loadThread = ListLoadThread(self)
self.startBtn = QPushButton("Start", self)
self.scrollLayout = QGridLayout(self.scrollWidget)
self.setWidget(self.scrollWidget)
self.setWidgetResizable(True)
self.setViewportMargins(10, 30, 10, 10)
self.scrollLayout.setAlignment(Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignHCenter)
self.startBtn.clicked.connect(self.start)
def start(self):
self.loadThread.addItem([i for i in range(100000)], self.add_item)
def add_item(self, item):
label = QLabel(f'Label {item}', self.scrollWidget)
count = self.scrollLayout.count()
self.scrollLayout.addWidget(label, count // 6, count % 6)
if __name__ == '__main__':
app = QApplication([])
window = ScrollArea()
window.show()
app.exec()
2. 异步
试了一下3000个是不卡的,数量再多也是会卡的,超过3000时,还是使用多线程好点
python
pip install qasync
python
import asyncio
import sys
from PySide6.QtCore import Qt
from PySide6.QtWidgets import QWidget, QApplication, QPushButton, QLabel, QScrollArea, QGridLayout
from qasync import QEventLoop, asyncSlot
class MainWindow(QScrollArea):
def __init__(self, parent=None):
super().__init__(parent)
self.scrollWidget = QWidget()
self.startBtn = QPushButton("Start", self)
self.scrollLayout = QGridLayout(self.scrollWidget)
self.setWidget(self.scrollWidget)
self.setWidgetResizable(True)
self.setViewportMargins(10, 30, 10, 10)
self.scrollLayout.setAlignment(Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignHCenter)
self.startBtn.clicked.connect(self.start_scroll)
async def add_item(self, item):
label = QLabel(f'Label {item}', self.scrollWidget)
count = self.scrollLayout.count()
self.scrollLayout.addWidget(label, count // 6, count % 6)
@asyncSlot()
async def start_scroll(self):
for i in range(1000):
await self.add_item(i)
if __name__ == "__main__":
app = QApplication(sys.argv)
loop = QEventLoop(app)
asyncio.set_event_loop(loop)
window = MainWindow()
window.show()
sys.exit(loop.run_forever())