PyQt6中QPixmapCache异常:循环内可查缓存,循环外find返回None
QPixmapCache循环内可找到对象,循环外返回None的问题解决
问题描述
开发PyQt6图片序列播放控件时,将图片通过QPixmapCache.insert()存入缓存后,插入循环内调用QPixmapCache.find()能正常获取QPixmap对象,但循环外调用该方法却返回None,无法读取缓存内容。相关代码及运行输出如下:
原代码
import sys from PyQt6.QtWidgets import ( QApplication, QMainWindow, QLabel ) from PyQt6.QtCore import Qt from PyQt6.QtGui import QPixmap, QPixmapCache from pathlib import Path class MainWindow(QMainWindow): def __init__(self): super().__init__() self.animating_label = QLabel('animation here') self.animating_label.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter) self.animating_label.pixmap().size().setWidth(200) self.animating_label.pixmap().size().setHeight(200) self.setCentralWidget(self.animating_label) parent_path = Path(__file__).parent self.images_path = parent_path / 'images/animation_set/' self.animating_label.setPixmap(QPixmap(self.images_path.__str__() + "/clock01.png")) self.pixmapcache_keys: [str] = [] self.load_images() test = QPixmapCache.find("clock02") try: self.animating_label.setPixmap(test) except: if test == None: print("Failure: QPixMapCache.find() returned", test) def load_images(self): image_suffixes = ['.jpg', '.png', '.gif', '.bmp'] imgs_found_count = 0 for filepath in self.images_path.iterdir(): if filepath.suffix in image_suffixes: imgs_found_count += 1 cache_key = filepath.stem self.pixmapcache_keys.append(cache_key) if not QPixmapCache.find(cache_key): pixmap = QPixmap(filepath.__str__()) QPixmapCache.insert(cache_key, pixmap) print("pixmap %s" % cache_key, QPixmapCache.find(cache_key)) print(imgs_found_count, "image(s) found in animation_set directory.", len(self.pixmapcache_keys), "keys loaded into QPixmapCache") app = QApplication(sys.argv) window = MainWindow() window.show() # start Qt event loop app.exec() print("Script complete.") sys.exit(1)
运行输出
pixmap clock04 <PyQt6.QtGui.QPixmap object at 0x101c84b30> pixmap clock10 <PyQt6.QtGui.QPixmap object at 0x101c84970> pixmap clock11 <PyQt6.QtGui.QPixmap object at 0x101c84b30> pixmap clock05 <PyQt6.QtGui.QPixmap object at 0x101c84970> ... 24 image(s) found in animation_set directory. 24 keys loaded into QPixmapCache Failure: QPixMapCache.find() returned None Script complete.
原因分析
- 默认缓存容量不足:QPixmapCache默认缓存上限为10240KB(10MB),当插入图片总大小超过该限制时,缓存会自动淘汰最早存入的条目,导致循环外查找时目标图片已被移除。
- 无效的尺寸修改逻辑:
self.animating_label.pixmap().size().setWidth(200)这类代码不会生效,因为QPixmap.size()返回的是QSize副本,修改副本无法改变原Pixmap的尺寸(非缓存失败直接原因)。 - 缓存判断逻辑不严谨:
if not QPixmapCache.find(cache_key)虽能判断空Pixmap,但更规范的方式是通过isNull()方法确认Pixmap有效性。
解决方案
- 增大缓存容量:程序启动时调用
QPixmapCache.setCacheLimit()设置足够大的缓存值,确保所有图片能存入缓存。 - 修正缓存判断逻辑:使用
isNull()方法准确判断缓存中是否存在有效Pixmap。 - 修复Label尺寸设置:改用
setFixedSize()直接设置Label显示尺寸,或对Pixmap缩放后再设置。
修改后的代码
import sys from PyQt6.QtWidgets import ( QApplication, QMainWindow, QLabel ) from PyQt6.QtCore import Qt from PyQt6.QtGui import QPixmap, QPixmapCache from pathlib import Path class MainWindow(QMainWindow): def __init__(self): super().__init__() self.animating_label = QLabel('animation here') self.animating_label.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter) # 修正Label尺寸设置方式 self.animating_label.setFixedSize(200, 200) self.setCentralWidget(self.animating_label) parent_path = Path(__file__).parent self.images_path = parent_path / 'images/animation_set/' self.animating_label.setPixmap(QPixmap(self.images_path / "clock01.png")) self.pixmapcache_keys = [] self.load_images() test = QPixmapCache.find("clock02") if not test.isNull(): self.animating_label.setPixmap(test) else: print("Failure: QPixMapCache.find() returned invalid pixmap") def load_images(self): image_suffixes = ['.jpg', '.png', '.gif', '.bmp'] imgs_found_count = 0 for filepath in self.images_path.iterdir(): if filepath.suffix in image_suffixes: imgs_found_count += 1 cache_key = filepath.stem self.pixmapcache_keys.append(cache_key) # 修正缓存存在性判断逻辑 pixmap = QPixmapCache.find(cache_key) if pixmap.isNull(): pixmap = QPixmap(filepath) QPixmapCache.insert(cache_key, pixmap) print(f"pixmap {cache_key}", QPixmapCache.find(cache_key)) print(f"{imgs_found_count} image(s) found in animation_set directory. {len(self.pixmapcache_keys)} keys loaded into QPixmapCache") if __name__ == "__main__": # 设置缓存容量为50MB(根据实际图片总大小调整) QPixmapCache.setCacheLimit(50 * 1024) app = QApplication(sys.argv) window = MainWindow() window.show() app.exec() print("Script complete.") sys.exit(0)
额外说明
- 缓存容量需根据图片总大小调整,避免设置过大占用过多内存。
Path对象可直接与字符串拼接,无需调用__str__(),简化代码。- 测试缓存查找时,优先判断
pixmap.isNull()而非是否为None,符合Qt API使用规范。
内容的提问来源于stack exchange,提问作者digitoxin
相关产品推荐
相关产品推荐

