我QGraphicsView
QGraphicsScene
,我需要在由scene
定义的rect
的有限区域内绘制未关闭的路径(可能包含线条或贝塞尔曲线)。
使用QPainterPath.intersected(path)
函数剪切关闭路径的方法很简单,但如果path
未关闭,那么intersected
关闭它(从开头到开始点添加一行)。
以下是说明我的问题的简化代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import functools
import sys
from PySide.QtCore import *
from PySide.QtGui import *
def path_through_points(points):
path = QPainterPath()
path.moveTo(*points[0])
for x, y in points[1:]:
path.lineTo(x, y)
return path
def path_through_points_workaround(points):
return path_through_points(points + list(reversed(points)))
if __name__ == "__main__":
app = QApplication(sys.argv)
scene = QGraphicsScene()
view = QGraphicsView(scene)
rect = QRectF(0, 0, 300, 300)
clip = QPainterPath()
clip.addRect(rect)
points = [(50, 50), (100, 100), (500, 300)]
def test_draw(path):
scene.clear()
scene.addRect(rect)
scene.addPath(path)
unclosed_path = path_through_points(points)
closed_path = path_through_points_workaround(points)
QTimer.singleShot(0, functools.partial(test_draw, unclosed_path))
QTimer.singleShot(2000, functools.partial(test_draw, unclosed_path.intersected(clip)))
QTimer.singleShot(4000, functools.partial(test_draw, closed_path.intersected(clip)))
view.resize(640, 480)
view.show()
sys.exit(app.exec_())
它绘制生成的路径:
解决方法:通过以path
顺序绘制来关闭reversed
。但是我的path
可能包含许多行/ beziers,因此它无效,并且使用双倍行反抗锯齿看起来很糟糕。
所以问题是如何在不改变路径生成函数逻辑的情况下在QGraphicsScene中剪切未闭合的路径或行?
更新
现在我正在使用以下功能:
def clipped_path(path, min_x, min_y, max_x, max_y):
""" Returns clipped path, supports unclosed paths of any kind
(lines, beziers)
NOTE: Resulting path can loose antialiasing
"""
path.connectPath(path.toReversed())
clip = QPainterPath()
clip.addRect(QRectF(min_x, min_y, max_x, max_y))
return path.intersected(clip)
更新2
建议使用@Hello W的更好方法:
class ClippedItemMixin(object):
def __init__(self, min_x, min_y, max_x, max_y):
self._clip_path = QtGui.QPainterPath()
self._clip_path.addRect(QtCore.QRectF(min_x, min_y, max_x, max_y))
super(ClippedItemMixin, self).__init__()
def paint(self, painter, *args, **kwargs):
painter.setClipPath(self._clip_path)
super(ClippedItemMixin, self).paint(painter, *args, **kwargs)
class ClippedPathItem(ClippedItemMixin, QtGui.QGraphicsPathItem):
pass
现在它看起来更好,因为抗锯齿效果正常。
答案 0 :(得分:1)
如何从QGraphicsPathItem
继承子类,然后重新实现它的paint方法并调用painter.setClipRect()