Python PyQt:覆盖QGraphicsView.drawItems

Python PyQt:覆盖QGraphicsView.drawItems,python,pyqt,Python,Pyqt,我需要自定义QGraphicsView的绘图过程,因此我重写drawItems方法,如下所示: self.graphicsview.drawItems=self.drawer.drawItems def drawItems(self, painter, items, options): for item in items: print "Processing", item # ... Do checking ... item.paint(

我需要自定义QGraphicsView的绘图过程,因此我重写drawItems方法,如下所示:

self.graphicsview.drawItems=self.drawer.drawItems
def drawItems(self, painter, items, options):
    for item in items:
        print "Processing", item
        # ... Do checking ...
        item.paint(painter, options, self.target)
其中,
self.graphicsview
是一个QGraphicsView,
self.drawer
是一个自定义类,其方法是
drawItems

在这个方法中,我检查几个标志以决定如何绘制每个项目,然后调用
item.paint
,如下所示:

self.graphicsview.drawItems=self.drawer.drawItems
def drawItems(self, painter, items, options):
    for item in items:
        print "Processing", item
        # ... Do checking ...
        item.paint(painter, options, self.target)
self.target
是QGraphicsView的QGraphicsCenter。
然而,一旦它到达
item.paint
,它就脱离了循环-没有任何错误。如果我在绘图周围添加条件,并为每种可能的QGraphicsItem类型粘贴应该执行的代码(通过查看Qt git源代码),那么一切都正常。

虽然不是一个很好的解决方案。。。我不明白它怎么会突然跳出循环?

循环突然退出的原因是抛出了一个异常。Python不处理它(没有<代码>尝试:块),所以它被传递给调用(Qt的C++代码),它不知道Python异常,所以它丢失了。 在循环周围添加一个try/except,您应该可以看到发生这种情况的原因

注意:由于Python2.4,您不应该再以这种方式重写方法

相反,您必须从QGraphicsView派生一个新类,并将
drawItems()
方法添加到此新类。这将正确地取代原来的方法


不要忘了在
\uuu init\uuu
方法中调用
super()
!否则,对象将无法正常工作。

绘制项目时会发生异常,但不会立即报告。在我的系统(PyQt 4.5.1、Python 2.6)上,当我使用以下方法进行修补时,不会报告任何异常:

def drawItems(painter, items, options):
    print len(items)
    for idx, i in enumerate(items):
        print idx, i
        if idx > 5:
            raise ValueError()
输出:

45
0 <PyQt4.QtGui.QGraphicsPathItem object at 0x3585270>
1 <PyQt4.QtGui.QGraphicsSimpleTextItem object at 0x356ca68>
2 <PyQt4.QtGui.QGraphicsSimpleTextItem object at 0x356ce20>
3 <PyQt4.QtGui.QGraphicsSimpleTextItem object at 0x356cc88>
4 <PyQt4.QtGui.QGraphicsSimpleTextItem object at 0x356cc00>
5 <PyQt4.QtGui.QGraphicsSimpleTextItem object at 0x356caf0>
6 <PyQt4.QtGui.QGraphicsSimpleTextItem object at 0x356cb78>
另外,您可以说
self.target
是场景对象。报告说:

此函数通常由QGraphicsView调用,以局部坐标绘制项的内容。。。小部件参数是可选的。如果提供,它指向正在绘制的小部件;否则,它是0。对于缓存的绘制,小部件始终为0

类型为
QWidget*
qgraphicscene
继承自
QObject
,并且不是一个小部件,因此这很可能也是错误的


尽管如此,如果根本没有报告异常,或者没有立即报告异常,这表明存在一些违规行为,您应该联系维护人员。

只是尝试添加此语句,
print item.paint
,以验证将调用哪个paint方法。上面印着“。内置的?我还有一个来自QGraphicsItem的自定义对象,上面的语句给出了“绑定方法…”。这种差异意味着什么?“内置”意味着调用Qt库中的编译代码,而“绑定方法”意味着调用Python代码。。。我的重写方法被正确调用了?这更多是偶然的,而不是有意的。好吧,只有在实例上调用它时它才会起作用。如果你在一个类上尝试这样的事情,它会失败。但是他在一个实例上这样做,这或多或少就是猴子补丁的想法。我不明白那个线程错误。但是,我得到“QGraphicsPolygonItem.paint()的参数2的类型无效”。参数2是选项参数,未作更改地传递。执行
type(options)
告诉我这是一个标准的Python列表-因此它是向下转换的,但不能再次“向上转换”。这一定是包装中的一个bug?只需重新阅读文档并进行一点尝试,就可以实现同样的事情(重新列出选项)。谢谢你的帮助!很奇怪,除非我用try/except-though来包围它,否则异常似乎不会出现。。。