2012-01-06 86 views
2

未封閉的路徑我有QGraphicsViewQGraphicsScene和我需要繪製未封閉的路徑(其可包含線或貝塞爾曲線)在由rect定義的scene有限區域。如何剪輯Qt中QGraphicsScene

有簡單的方式來夾通過使用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_()) 

它吸引生成的路徑:

  1. 沒有削波。
  2. 隨着剪輯(路徑關閉,而不是隻是剪輯) - 這是我無法接受的。
  3. 最後,我想得到的結果(但是它是通過解決方法達成的)。

解決方法:關閉path通過在reversed的訂單中繪製它。但我的path可能包含許多行/ beziers,所以它是無效的,並且抗鋸齒看起來不好用雙線。

所以問題是如何在不改變路徑生成函數的邏輯的情況下在QGraphicsScene中修剪未封閉的路徑或線?

UPDATE

現在,我使用下面的函數:

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謝謝了'path.connectPath(path.toReversed())'伎倆是偉大的! – 2013-06-19 10:54:45

回答

1

如何從QGraphicsPathItem繼承,然後重新實現它的paint方法,並呼籲painter.setClipRect()

+0

非常感謝!它的工作。 – reclosedev 2012-05-08 11:40:57