python - QGraphicsObject 需要显式更新才能重绘
问题描述
我有一个QGraphicsPixmapItem
内容随鼠标单击而变化的内容。当所有交互式事件都在派生自的类中处理时,一切都很好QGraphicsPixmapItem
:
import numpy as np
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QGraphicsPixmapItem, QGraphicsScene, QGraphicsView, QMainWindow
class MyQGraphicsPixmapItem(QGraphicsPixmapItem):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setNewImage()
def setNewImage(self):
im = np.random.randint(255, size=(256, 256), dtype=np.uint8)
pix = QPixmap.fromImage(QImage(im, im.shape[1], im.shape[0], QImage.Format_Grayscale8))
self.setPixmap(pix)
def mousePressEvent(self, event):
self.setNewImage()
app = QApplication([])
window = QMainWindow()
window.setGeometry(100, 100, 400, 400)
view = QGraphicsView()
scene = QGraphicsScene()
gpix = MyQGraphicsPixmapItem()
scene.addItem(gpix)
view.setScene(scene)
window.setCentralWidget(view)
window.show()
app.exec()
然而,与其在类中处理事件,我希望能够在其他地方处理它们,通常作为回调。在这个答案中,提供了两个选项:使用QGraphicsObject
,或使用场景事件过滤器,强烈建议使用,因为前者很重。但是,AFAIU,场景事件过滤器使一个图形项的事件被另一个图形项处理;我想要更一般的东西,QWidget
可以处理事件。所以我认为在我的情况下我需要使用QGraphicsObject
.
我对上面的脚本做了一个简单的修改,QGraphicsPixmapItem
将QGraphicsObject
. 然而,令我惊讶的是,点击时图像并没有刷新。
import numpy as np
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QGraphicsObject, QGraphicsPixmapItem, QGraphicsScene, QGraphicsView, QMainWindow
class MyQGraphicsObject(QGraphicsObject):
def __init__(self, gpix):
super().__init__(gpix)
self.gpix = gpix
self.setNewImage()
def setNewImage(self):
im = np.random.randint(255, size=(256, 256), dtype=np.uint8)
pix = QPixmap.fromImage(QImage(im, im.shape[1], im.shape[0], QImage.Format_Grayscale8))
self.gpix.setPixmap(pix)
# self.update() # needs to be uncommented to refresh
def mousePressEvent(self, event):
self.setNewImage()
def boundingRect(self):
return self.gpix.boundingRect()
def paint(self, painter, option, widget):
return self.gpix.paint(painter, option, widget)
app = QApplication([])
window = QMainWindow()
window.setGeometry(100, 100, 400, 400)
view = QGraphicsView()
scene = QGraphicsScene()
opix = MyQGraphicsObject(QGraphicsPixmapItem())
scene.addItem(opix)
view.setScene(scene)
window.setCentralWidget(view)
window.show()
app.exec()
只有当我手动添加 aself.update()
时,图像才会刷新。当然,这解决了问题,但我有一种不应该需要的感觉,而且我使用QGraphicsObject
错误。是这样吗,还是update
真的需要手册?
解决方案
update()
调用方法是正确的。
TL; 博士;
在哪些情况下需要调用更新?
每当开发人员需要调用paint() 方法(或小部件上的paintEvent)时
为什么在 QGraphicsPixmapItem 的情况下不需要调用它,但在 QGraphicsObject 中却是必要的?
在 QGraphicsPixmapupdate()
方法被调用,你可以验证源代码是否被修改:
void QGraphicsPixmapItem::setPixmap(const QPixmap &pixmap)
{
Q_D(QGraphicsPixmapItem);
prepareGeometryChange();
d->pixmap = pixmap;
d->hasShape = false;
update();
}
换句话说,在QGraphicsItem中你不再需要调用它,因为setPixmap方法已经做了,不像QGraphicsObject没有它,所以需要调用update()来强制调用paint方法。
推荐阅读
- php - 强制用户在进入结账页面之前计算出货量或选择一种方法
- byobu - 命令 byobu-quiet 有什么影响
- python - 不使用递归将嵌套字典解开为简单字典
- continuous-integration - 在侦听 development_status 事件时,如何对 GitHub 操作使用依赖项缓存?
- javascript - 我想为菜单创建波浪背景
- html - 是否可以在 HTML 文件输入中预设在线图像?
- ios - 在 iOS 应用和 Rails 后端之间传递用户 ID 以进行应用内购买
- android - Xamarin Native 上的 MSAL - OnActivityResult 从未被调用,导致应用程序在 BrowserTabActivity 上挂起
- go - 在 Viper 中访问嵌套 YAML 结构时出现问题
- javascript - 如何通过 node.js 服务器路由 html 表单提交以更新 .js 文件中变量的值