窗口最小化恢复时图片闪烁修复
问题现象
阅读漫画时,窗口最小化再恢复,图片会先消失 ~0.5s(中间显示页码文字),然后才重新出现。
根因分析
DeviceCoordinateCache — 缓存在设备像素级别,窗口最小化时设备上下文被销毁,所有 item 缓存失效。
MinimalViewportUpdate — 最小化恢复后不立即标记整个视口为脏区,重绘延迟。
ResetSize → ChangeReadMode2 → allItemsState.clear() — 窗口事件触发 ResetSize,调用 ChangeReadMode2 清掉图片加载状态后,PixmapToLabel 把已缓存的图片替换成页码文字,造成「原图 → 页码 → 原图」的闪烁链。
修改文件
src/view/read/read_graphics.py,共 5 处改动:
改动 1:DeviceCoordinateCache → ItemCoordinateCache(4 处)
ItemCoordinateCache 缓存在逻辑坐标级别,不受设备上下文销毁影响。
位置 1 — InitHelp,滚动模式 label pool:
self.graphicsScene.addItem(proxy)
- proxy.setCacheMode(QGraphicsItem.DeviceCoordinateCache)
+ proxy.setCacheMode(QGraphicsItem.ItemCoordinateCache)
位置 2 — InitReadMode,左右/等宽模式:
self.graphicsItem1.setCacheMode(
- QGraphicsItem.DeviceCoordinateCache
+ QGraphicsItem.ItemCoordinateCache
)
位置 3+4 — InitReadMode,双页模式:
self.graphicsItem1.setCacheMode(
- QGraphicsItem.DeviceCoordinateCache
+ QGraphicsItem.ItemCoordinateCache
)
self.graphicsItem2.setCacheMode(
- QGraphicsItem.DeviceCoordinateCache
+ QGraphicsItem.ItemCoordinateCache
)
改动 2:MinimalViewportUpdate → SmartViewportUpdate
- self.setViewportUpdateMode(QGraphicsView.MinimalViewportUpdate)
+ self.setViewportUpdateMode(QGraphicsView.SmartViewportUpdate)
Smart 模式能正确判断窗口状态变化后该重绘什么。
改动 3:新增 showEvent 强制即时重绘
在 ReadGraphicsView 类中新增,窗口恢复时不等事件循环调度,立即刷新视口:
+ def showEvent(self, event):
+ """窗口恢复显示时强制立即重绘视口,避免闪烁"""
+ super().showEvent(event)
+ self.viewport().update()
改动 4:__init__ 新增尺寸追踪变量
self.initReadMode = None
+ self._lastWidth = None
+ self._lastHeight = None
改动 5:重写 ResetSize — 区分最小化恢复 vs 真正 resize
之前的实现把一切窗口事件都走重量级 ChangeReadMode2(清空状态→重建),现在按尺寸是否变化分流:
def ResetSize(self):
- self.qtTool.ChangeReadMode2(self.readImg.stripModel.value, keepScale=True)
+ if not self.initReadMode:
+ return
+ w, h = self.width(), self.height()
+ # 最小化后恢复 — 尺寸不变,只刷新视口
+ if w == self._lastWidth and h == self._lastHeight:
+ self.viewport().update()
+ return
+ # 尺寸确实变了 — 重算位置 + 重新渲染图片
+ self._lastWidth, self._lastHeight = w, h
+ maxNum = self.maxPic
+ if ReadMode.isScroll(self.initReadMode):
+ self.ResetLabelSize(maxNum)
+ for index, proxy in enumerate(self.allItems):
+ value = self.labelSize.get(index)
+ if self.initReadMode == ReadMode.UpDown:
+ proxy.setPos(0, value / self.devicePixelRatioF())
+ else:
+ proxy.setPos(value / self.devicePixelRatioF(), 0)
+ elif ReadMode.isDouble(self.initReadMode):
+ self.graphicsItem2.setPos(self.width() // 2, 0)
+ self.ResetMaxNum()
+ self.readImg.ShowImgAll()
效果
- 最小化恢复:尺寸未变 → 仅
viewport().update(),不重建任何资源,无闪烁。
- 真正 resize:尺寸变化 → 重算位置 +
ShowImgAll() 以新尺寸重渲染图片,图片正确适配。
窗口最小化恢复时图片闪烁修复
问题现象
阅读漫画时,窗口最小化再恢复,图片会先消失 ~0.5s(中间显示页码文字),然后才重新出现。
根因分析
DeviceCoordinateCache— 缓存在设备像素级别,窗口最小化时设备上下文被销毁,所有 item 缓存失效。MinimalViewportUpdate— 最小化恢复后不立即标记整个视口为脏区,重绘延迟。ResetSize → ChangeReadMode2 → allItemsState.clear()— 窗口事件触发ResetSize,调用ChangeReadMode2清掉图片加载状态后,PixmapToLabel把已缓存的图片替换成页码文字,造成「原图 → 页码 → 原图」的闪烁链。修改文件
src/view/read/read_graphics.py,共 5 处改动:改动 1:
DeviceCoordinateCache→ItemCoordinateCache(4 处)ItemCoordinateCache缓存在逻辑坐标级别,不受设备上下文销毁影响。位置 1 —
InitHelp,滚动模式 label pool:位置 2 —
InitReadMode,左右/等宽模式:位置 3+4 —
InitReadMode,双页模式:改动 2:
MinimalViewportUpdate→SmartViewportUpdateSmart模式能正确判断窗口状态变化后该重绘什么。改动 3:新增
showEvent强制即时重绘在
ReadGraphicsView类中新增,窗口恢复时不等事件循环调度,立即刷新视口:改动 4:
__init__新增尺寸追踪变量改动 5:重写
ResetSize— 区分最小化恢复 vs 真正 resize之前的实现把一切窗口事件都走重量级
ChangeReadMode2(清空状态→重建),现在按尺寸是否变化分流:效果
viewport().update(),不重建任何资源,无闪烁。ShowImgAll()以新尺寸重渲染图片,图片正确适配。