2012-01-06 2 views
2

에서 닫히지 클리핑하는 클립 어떻게 QGraphicsSceneQGraphicsView가 나는 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. 마지막으로 결과를 얻으려고합니다 (그러나 해결 방법으로 도달했습니다).

해결 방법 : reversed 순서로 그려서 path을 닫으십시오. 그러나 내 path에는 많은 선/베 지어가 포함될 수 있으므로 효과가 없으며 앤티 앨리어싱이 두 줄로 나쁘게 보입니다.

그래서 경로 생성 함수의 논리를 변경하지 않고 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를 :

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