当前位置: 首页 > news >正文

Qt小组件 - 5 图片懒加载样例

加载本地大图片会有卡顿现象,因为imageLabel是同步加载

imageLabelQt小组件 - 3 imageLabel

Qt小组件 - 2(布局)瀑布流布局,GridLayout,FlowLayout

LoadImageThread最好使用线程池代替否则创建线程过多阻碍主线程刷新

# coding: utf-8
import sys
from pathlib import Path
from typing import List, Unionfrom PySide6.QtCore import QRect, QThread, Signal, Qt, QThreadPool, QTimer
from PySide6.QtGui import QImage, QPixmap
from PySide6.QtWidgets import QVBoxLayout, QApplication, QScrollArea, QWidgetfrom components import ImageLabel, WaterfallLayoutclass LoadImageThread(QThread):loadSignal = Signal(QImage)def __init__(self, parent=None):super().__init__(parent)self.url = Nonedef run(self):if not self.url:returnif isinstance(self.url, (str, Path)):url = str(self.url)image = QImage(url)else:image = self.urlself.loadSignal.emit(image)def setUrl(self, url):self.url = urlself.start()class LazyLoadThread(QThread):loadSignal = Signal(object, object)def __init__(self, parent=None):super().__init__(parent)self.isStopped = Falseself.rect = QRect()self.labels = []  # type: List[LazyLoadImage]def run(self):try:self.verify()except Exception as e:print(e)def setData(self, rect: QRect, labels: List['LazyLoadImage']):self.rect = rectself.labels = labelsself.start()def verify(self):viewport_rect: QRect = self.rectfor item in self.labels:item_rect = item.geometry()if viewport_rect.intersects(item_rect):self.loadSignal.emit(item, True)else:self.loadSignal.emit(item, False)def stop(self):self.isStopped = Trueself.terminate()class LazyLoadImage(ImageLabel):def _postInit(self):self.dataSource = Noneself.loadThread = LoadImageThread(self)self.loadThread.loadSignal.connect(self.setImage)self.finished.connect(self.on_finished)def setDataSource(self, source: str):self.dataSource = sourcedef setImageUrl(self, url: str):self.loadThread.setUrl(url)def setLoading(self, loading: bool):if loading and self.isNull():if self.dataSource.startswith('http'):self.setUrl(self.dataSource)else:self.setImageUrl(self.dataSource)else:if self.isNull():returnself.setImageUrl(QImage())class LazyLoadScrollArea(QScrollArea):def __init__(self, parent=None):super().__init__(parent)self.labels = []self.timer = QTimer(self) # 避免多次加载self.lazy_load_thread = LazyLoadThread(self)self.lazy_load_thread.loadSignal.connect(self.on_load_signal)self.setWidget(QWidget())self.widget().setLayout(WaterfallLayout())self.setWidgetResizable(True)self.verticalScrollBar().valueChanged.connect(self.start)self.timer.timeout.connect(self.updateLazy)self.timer.setSingleShot(True)self.timer.setInterval(150)def on_load_signal(self, item: LazyLoadImage, loading: bool):try:item.setLoading(loading)item.finished.connect(lambda: item.scaledToWidth(item.width()))except Exception as e:print(e)def start(self):self.timer.stop()self.timer.start()def updateLazy(self):rect = self.viewport().rect()rect.translate(self.horizontalScrollBar().value(), self.verticalScrollBar().value())self.lazy_load_thread.setData(rect, self.labels)self.updateGeometry()def add_image(self, url: str):image_label = LazyLoadImage()image_label.setDataSource(url)image_label.setScaledContents(True)image_label.setMinimumHeight(400)self.labels.append(image_label)layout = self.widget().layout()layout.addWidget(image_label)if layout.sizeHint().height() < self.height():self.start()def resizeEvent(self, event):self.start()super().resizeEvent(event)def closeEvent(self, event):self.lazy_load_thread.stop()self.timer.stop()super().closeEvent(event)if __name__ == "__main__":app = QApplication(sys.argv)scroll_area = LazyLoadScrollArea()scroll_area.setWindowTitle("图片懒加载示例")scroll_area.resize(400, 600)# 添加一些图片URL到滚动区域image_urls = ["http://browser9.qhimg.com/bdm/1024_632_0/t010824ab8b5cdfa138.jpg","http://browser9.qhimg.com/bdm/512_316_0/t010448c46c1ecf7cab.jpg","http://browser9.qhimg.com/bdm/1024_632_0/t013a4ed4683039d101.jpg"]for url in image_urls:scroll_area.add_image(url)for url in Path(r'G:\手机\壁纸\碧蓝航线\5.26立绘\Picture').glob('*.*'):scroll_area.add_image(url.as_posix())scroll_area.show()sys.exit(app.exec())

连续创建了2675个组件左右,初次打开需要10S左右的时间

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

http://www.lryc.cn/news/590260.html

相关文章:

  • 服务攻防-Java组件安全数据处理FastJsonJackSonXStream自动BP插件CVE漏洞
  • 算法穿上隐身衣:数据交易中数据黑箱与算法透明性的法律义务边界
  • 大数据方向研究生就业前景与竞争力分析
  • “重复”定义函数的睿智(Python/与ai助手“智普清言”深度交流)
  • 综合实验(重点:ACL)
  • 【kubernetes】--安全认证机制
  • 快速掌握 Kafka:从核心概念到生产级部署指南
  • 【ROS/DDS】FastDDS:C++编写一个发布者和订阅者应用程序(三)
  • C# 8.0 创建一个简单的控制台应用程序
  • Prompt Engineering 快速入门+实战案例
  • 面向向量检索的教育QA建模:九段日本文化研究所日本语学院的Prompt策略分析(6 / 500)
  • 基于大数据电信诈骗行为分析与可视化预测系统的设计与实现【海量数据、多种机器学习对比、数据优化、过采样】
  • 多房间 WebSocket 连接管理设计:从单例模式到多终端连接池
  • 【Qt】构建和编译 Qt 程序时如何减少生成的二进制可执行文件的大小
  • Navicat操作指南:MySQL数据库配置与Todo应用部署
  • MySQL 配置性能优化赛:用创意配置解锁性能潜能
  • 《Java语言程序设计》1.2.4复习题
  • 海盗王如何拍摄和打包小地图
  • 深度赋能推客,让 “业余选手” 变 “带货高手”​
  • Xsens人形机器人拟人动作AI训练,提升机器人工作精度与效率
  • HertzBeat 监控 SpringBoot 使用案例
  • 基于dcmtk的dicom工具 第二章 图像接受StoreSCP(1)
  • windows内核研究(进程与线程-等待链表和调度链表和线程切换)
  • 非控制器(如 Service、工具类)中便捷地获取当前 HTTP 请求的上下文信息
  • 16路串口光纤通信FPGA项目实现指南
  • 数据结构-1(顺序表)
  • 关于 OpenAI 的反思
  • GESP2025年6月认证C++四级( 第三部分编程题(2)排序)
  • 多态,内部类(匿名内部类),常用API(1)
  • HTTP vs HTTPS