2

如果你有一个 QGraphicsEllipseItem 比它的高(扁平)宽得多,它会在它自己的边界之外绘制。这意味着它不能正确绘制,并且在您拖动它时会在屏幕上留下伪影。这重现了这个问题(向非 Pythonistas 道歉,但对于 C++ers 应该是完全可以理解的):

import sys
from PySide import QtCore, QtGui

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    scene = QtGui.QGraphicsScene()
    scene.setSceneRect(0, 0, 400, 400)
    ellipse = QtGui.QGraphicsEllipseItem(QtCore.QRectF(0, 0, 320, 5))
    ellipse.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
    ellipse.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
    ellipse.setPos(40, 200)
    ellipse.setPen(QtGui.QPen(QtCore.Qt.red, 1))
    scene.addItem(ellipse)
    view = QtGui.QGraphicsView(scene)
    view.show()
    sys.exit(app.exec_())

关键是QGraphicsEllipseItem的宽度是320,高度正好是5。如果选择椭圆,选择框的虚线画在item的边界处,可以看到左右两边椭圆的边缘在这些边界之外。如果您然后将项目拖动到您周围,您将获得工件。

这是在 Windows 7 64 位上,使用 PySide 1.1.2,如果重要的话。

如果您打开抗锯齿(例如view.setRenderHint(QtGui.QPainter.Antialiasing)),椭圆会在其边界内绘制,一切都很好。

我宁愿选择绘制锯齿或抗锯齿,但作为最后的手段,我总是可以绘制抗锯齿,除非有人有更好的解决方案。我对 QGraphicsEllipseItem 进行了子类化,并在基类的边界矩形周围放置了大量填充,例如:

def boundingRect(self):
    return QGraphicsEllipseItem.boundingRect(self).adjusted(-40, -40, 40, 40)

这解决了很多情况下的问题,但是如果椭圆非常大,您可能会超出界限,因此很难知道要添加多少填充,无论如何这是一个相当糟糕的解决方案因为这意味着在大多数情况下我的界限都在数英里之外(对碰撞检测等的影响)。

您还可以通过更改视图上的更新模式来停止工件,即:

view.setViewportUpdateMode(QtGui.QGraphicsView.FullViewportUpdate)

不得不这样做来处理一种 GraphicsItem 类型的绘画,以防万一它非常扁平,这似乎有点难过......

我想我可以尝试在我自己的 QGraphicsEllipseItem 子类中“正确地”绘制东西,但我怀疑基类只是告诉画家画一个椭圆,所以我不得不乱七八糟想出我的自己的椭圆绘制算法,不使用画家一...

还有其他想法吗?什么似乎是最不坏的选择?我倾向于只打开 FullViewportUpdate。

4

1 回答 1

3

这是 QPen 的问题。

如果您使用宽度更大的 QPen(例如 1.2),问题就会消失(如果我没记错的话,默认情况下,对于连接,QPen 在找到交叉点时会扩展线条)。

于 2013-03-05T15:51:31.433 回答