2012-01-06 10 views
2

私はQGraphicsViewQGraphicsSceneとしています。限定された範囲内の閉じられていないパス(線やベジエ曲線を含む場合があります)をrectで定義する必要があります。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. 最後に、私が得たい結果(しかし、回避策では到達しています)。

回避策:reversedためにそれを描くことによってpathあります。しかし、私のpathには多くの行/ベジエが含まれている可能性がありますので、効果的ではありません。アンチエイリアスは2行で悪く見えます。

QGraphicsSceneでパス生成関数のロジックを変更せずに、閉じられていないパスや行をクリップする方法はありますか?

UPDATE

今、私は次の関数使用しています:@Hello Wが提案されているよう

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) 

はUPDATE 2

より良い方法を:

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は())'トリックは素晴らしいです! –

答えて

1

がどのようにQGraphicsPathItemからサブクラス化し、それのpaintメソッドを再実装し、painter.setClipRect()

+0

ありがとうございます!それは働いている。 – reclosedev

関連する問題