如何在QGraphicsItem元类中正确调用基类mouseMoveEvent方法?
问题描述
我想给多个继承自QGraphicsItem的类添加相同的自定义函数,目前的重复实现方式如下:
class QGraphicsRectItem(QGraphicsRectItem): def mouseMoveEvent(self, event): print( "mouseMoveEvent :: event pos =(%.1f, %.1f) " %( event.pos().x(), event.pos().y() ) ) super().mouseMoveEvent( event ) class QGraphicsEllipseItem(QGraphicsEllipseItem): def mouseMoveEvent(self, event): print( "mouseMoveEvent :: event pos =(%.1f, %.1f) " %( event.pos().x(), event.pos().y() ) ) super().mouseMoveEvent( event ) class QGraphicsPixmapItem(QGraphicsPixmapItem): def mouseMoveEvent(self, event): print( "mouseMoveEvent :: event pos =(%.1f, %.1f) " %( event.pos().x(), event.pos().y() ) ) super().mouseMoveEvent( event ) class QGraphicsSimpleTextItem(QGraphicsSimpleTextItem): def mouseMoveEvent(self, event): print( "mouseMoveEvent :: event pos =(%.1f, %.1f) " %( event.pos().x(), event.pos().y() ) ) super().mouseMoveEvent( event )
为简化代码,我尝试用继承自type(QGraphicsItem)的元类批量注入该自定义方法,但在元类中编写super().mouseMoveEvent( event )时遇到问题,当前元类实现无法正常工作:
from types import FunctionType class QGraphicsItemMeta(type(QGraphicsItem)): def __new__(cls, name, bases, dct): print("name= %s" %(name)) print("bases= %s" %(bases)) print("dct=", dct) newDct = {} for name, method in dct.items(): if type(method) is FunctionType: print("method name= %s" % (name)) newDct[name] = method else: print("attribut name= %s" % (name)) newDct[name] = method def mouseMoveEventMyCustomize(self, event): print( "mouseMoveEventNew :: event pos =(%.1f, %.1f) " %( event.pos().x(), event.pos().y() ) ) super().mouseMoveEvent( event ) newDct['mouseMoveEvent'] = mouseMoveEventMyCustomize return super().__new__(cls, name, bases, newDct) class QGraphicsRectItem(QGraphicsRectItem, metaclass = QGraphicsItemMeta): pass class QGraphicsEllipseItem(QGraphicsEllipseItem, metaclass = QGraphicsItemMeta): pass class QGraphicsPixmapItem(QGraphicsPixmapItem, metaclass = QGraphicsItemMeta): pass class QGraphicsSimpleTextItem(QGraphicsSimpleTextItem, metaclass = QGraphicsItemMeta): pass
我曾尝试将该行代码替换为bases().mouseMoveEvent( event ),但依然无法解决问题,请问该如何修正?
解决方案
问题核心在于元类中定义的mouseMoveEventMyCustomize方法里的super()调用没有绑定当前实例的类上下文,无法正确定位父类方法;而bases()会创建新的基类实例,并非调用当前实例的父类方法,因此无效。以下是两种可靠的修正方案:
方法一:使用装饰器(推荐,更简洁)
无需元类,通过装饰器批量为类注入自定义逻辑:
def add_custom_mouse_move(cls): # 保存原有方法,避免覆盖类自身定义的逻辑 original_mouse_move = cls.mouseMoveEvent def new_mouse_move(self, event): print("mouseMoveEventNew :: event pos =(%.1f, %.1f) " %( event.pos().x(), event.pos().y() )) # 调用原方法 original_mouse_move(self, event) cls.mouseMoveEvent = new_mouse_move return cls # 用装饰器批量处理目标类 @add_custom_mouse_move class QGraphicsRectItem(QGraphicsRectItem): pass @add_custom_mouse_move class QGraphicsEllipseItem(QGraphicsEllipseItem): pass @add_custom_mouse_move class QGraphicsPixmapItem(QGraphicsPixmapItem): pass @add_custom_mouse_move class QGraphicsSimpleTextItem(QGraphicsSimpleTextItem): pass
方法二:修正元类实现
如果坚持使用元类,需通过实例的__class__绑定正确的上下文来调用父类方法:
from types import FunctionType class QGraphicsItemMeta(type(QGraphicsItem)): def __new__(cls, name, bases, dct): def mouseMoveEventMyCustomize(self, event): print("mouseMoveEventNew :: event pos =(%.1f, %.1f) " %( event.pos().x(), event.pos().y() )) # 通过实例的实际类构建super对象,确保找到正确的父类方法 super(self.__class__, self).mouseMoveEvent(event) # 仅当类自身未定义mouseMoveEvent时才注入,保留灵活性 if 'mouseMoveEvent' not in dct: dct['mouseMoveEvent'] = mouseMoveEventMyCustomize # 移除不必要的newDct复制逻辑,直接修改传入的dct return super().__new__(cls, name, bases, dct) # 使用元类创建目标类 class QGraphicsRectItem(QGraphicsRectItem, metaclass=QGraphicsItemMeta): pass class QGraphicsEllipseItem(QGraphicsEllipseItem, metaclass=QGraphicsItemMeta): pass class QGraphicsPixmapItem(QGraphicsPixmapItem, metaclass=QGraphicsItemMeta): pass class QGraphicsSimpleTextItem(QGraphicsSimpleTextItem, metaclass=QGraphicsItemMeta): pass
内容的提问来源于stack exchange,提问作者jljPatch
相关产品推荐
相关产品推荐

