2014-02-14 14 views
2

我有一個QGraphicsScene我希望用戶繪製/移動東西。目前我可以畫出我想要的所有形狀(即[un]填充的矩形和橢圓,線條和三次貝塞爾曲線),派生出QGraphics*ItemQGraphicsScene中的視覺像素完美選擇

我也可以實現對這些項目的選擇,但我想要某種像素完美的選擇。例如,即使鼠標不在實線上,也可以在曲線旁邊單擊時選擇曲線。空矩形或橢圓形也是如此,點擊它們中間的孔也可以選擇它們。

這是因爲contains的工作方式,它不符合我的需要:它基本上檢查點是否在邊界矩形中。 setBoundingRegionGranularity(1)沒有解決任何問題(以防萬一)。

我也試着直接檢查點是否包含在我的項目的QPainterPath,但這給了我相同的結果。

我怎樣才能視覺選擇我的形狀?

我現在看到的唯一解決方案是重新實現我自己的每個形狀的contains函數,但這可能相當複雜,如果可能的話,我真的希望通過Qt完成這項工作。

我正在使用Python 3.3和PyQt 5(.1.1 IIRC),但這與Qt框架相比語言/綁定更相關,並且C++中的答案也很好。

回答

1

QGraphicsPathItem::shape包含它正在顯示的路徑,包括其內部區域。你期望的行爲更像QGraphicsPixmapItem。如果它的shapeModeQGraphicsPixmapItem::MaskShape(默認),其形狀將只包含不透明點。您可能想要在像素圖上繪製曲線並在場景中顯示像素圖並享受默認行爲。您也可以重新定義QGraphicsPathItem::shape並實現此行爲。工作實例,C++(可以很容易地適應於Python):

class MyGraphicsPathItem : public QGraphicsPathItem { 
public: 
    MyGraphicsPathItem() {} 
    QPainterPath shape() const { 
    QRectF rect = path().boundingRect(); 
    QImage canvas(rect.size().toSize(), QImage::Format_ARGB32); 
    canvas.fill(qRgba(0, 0, 0, 0)); 
    QPainter painter(&canvas); 
    painter.setPen(pen()); 
    painter.drawPath(path().translated(-rect.topLeft())); 
    painter.end(); 
    QPainterPath result; 
    result.addRegion(QPixmap::fromImage(canvas).mask()); 
    return result.translated(rect.topLeft()); 
    } 
}; 

用法:

MyGraphicsPathItem* item = new MyGraphicsPathItem(); 
item->setPath(path); 
item->setFlag(QGraphicsItem::ItemIsSelectable); 
item->setPen(QPen(Qt::green, 3)); 
scene->addItem(item); 

注意,此實現是相當緩慢。謹慎使用。

+0

感謝您的回答。但是,使用Pixmaps會在形狀上放棄抗鋸齒,我錯過了什麼? –

+0

您需要在用於創建像素圖的畫家中啓用'QPainter :: Antialiasing'提示。如果你使用像素縮放,你應該設置'QGraphicsPixmapItem :: setTransformationMode(Qt :: SmoothTransformation)'。 –