2016-06-13 23 views
2

私は、テキストボックスの位置に基づいて調整されるラインに接続されることになっている2つのサブクラス化されたQGraphicsRectItemを持っています。 Qtのdiagramscene example接続されたアイテムの変更でのカスタムQGraphicsItemの位置の更新

はサブクラスQGraphicsPolygonItemitemChanged方法は矢印の位置を更新するsetLineを呼び出し、接続矢印のupdatePositionメソッドを呼び出しdocus。私の場合、setLineQGraphicsLineItemの代わりにQGraphicsItemのサブクラス化として呼び出すことはできません。

下記のArrowクラスのupdatePositionメソッドを実装して、QGraphicsItemの位置を更新するにはどうすればよいですか?以下は、テキストボックスがクリックされて移動されたときに現在何が起こっているかを示す実行可能な例です。

enter image description here

import sys 
from PyQt4.QtGui import * 
from PyQt4.QtCore import * 


class Arrow(QGraphicsItem): 

    def __init__(self, startItem, endItem, parent=None, scene=None): 
     super().__init__(parent, scene) 

     self.startItem = startItem 
     self.endItem = endItem 

    def boundingRect(self): 
     p1 = self.startItem.pos() + self.startItem.rect().center() 
     p3 = self.endItem.pos() + self.endItem.rect().center() 
     bounds = p3 - p1 
     size = QSizeF(abs(bounds.x()), abs(bounds.y())) 
     return QRectF(p1, size) 

    def paint(self, painter, option, widget=None): 

     p1 = self.startItem.pos() + self.startItem.rect().center() 
     p3 = self.endItem.pos() + self.endItem.rect().center() 

     pen = QPen() 
     pen.setWidth(1) 
     painter.setRenderHint(QPainter.Antialiasing) 

     if self.isSelected(): 
      pen.setStyle(Qt.DashLine) 
     else: 
      pen.setStyle(Qt.SolidLine) 

     pen.setColor(Qt.black) 
     painter.setPen(pen) 
     painter.drawLine(QLineF(p1, p3)) 
     painter.setBrush(Qt.NoBrush) 

    def updatePosition(self): 
     #Not sure what to do here... 


class TextBox(QGraphicsRectItem): 

    def __init__(self, text, position, rect=QRectF(0, 0, 200, 100), 
       parent=None, scene=None): 
     super().__init__(rect, parent, scene) 

     self.setFlags(QGraphicsItem.ItemIsFocusable | 
         QGraphicsItem.ItemIsMovable | 
         QGraphicsItem.ItemIsSelectable) 

     self.text = QGraphicsTextItem(text, self) 

     self.setPos(position) 

     self.arrows = [] 

    def paint(self, painter, option, widget=None): 
     painter.setPen(Qt.black) 
     painter.setRenderHint(QPainter.Antialiasing) 
     painter.setBrush(Qt.white) 
     painter.drawRect(self.rect()) 

    def addArrow(self, arrow): 
     self.arrows.append(arrow) 

    def itemChange(self, change, value): 
     if change == QGraphicsItem.ItemPositionChange: 
      for arrow in self.arrows: 
       arrow.updatePosition() 

     return value 


if __name__ == "__main__": 

    app = QApplication(sys.argv) 

    view = QGraphicsView() 
    scene = QGraphicsScene() 
    scene.setSceneRect(0, 0, 500, 1000) 
    view.setScene(scene) 

    textbox1 = TextBox("item 1", QPointF(50, 50), scene=scene) 
    textbox1.setZValue(1) 
    textbox2 = TextBox("item 2", QPointF(100, 500), scene=scene) 
    textbox2.setZValue(1) 

    arrow = Arrow(textbox1, textbox2, scene=scene) 
    arrow.setZValue(0) 

    textbox1.addArrow(arrow) 
    textbox2.addArrow(arrow) 

    view.show() 

    sys.exit(app.exec_()) 
+0

最も簡単な方法は、 'QGraphicsItemGroup'または親子関係を使用することです。それを実行するこれらの2つの方法がすべてを世話するので、物事を一緒に動かすために、それ以降は何もする必要はありません。 – rbaleksandar

+0

私はあなたの提案が、すべてのアイテムが同時に動いているが、他のアイテムのどれも動かないケースのために働いているのを見ることができました。それは事実ですか? – pbreach

+1

私はそうは思わない。だから、基本的には、接続を「ストレッチ」したいのに、選択したノードだけを移動したいのですか?もしそうなら、[ここ](http://www.walletfox.com/course/qgraphicsitemruntimedrawing.php)を見てください。基本的にはマウスを動かしながら描画を行います。ノードの1つを動かすたびに、移動したノードが放置されるまで接続を再作成して更新する必要があります。移動された接続は最後の接続になります。 – rbaleksandar

答えて

3

アイテムの位置は、実際に問題ではありません - それは0,0のままにすることができます - バウンディングボックスを提供し、それはあなたの矢印に従ってされる(正しい::バウンディングボックスの実装)。したがって、バウンディングボックスの変更とupdatePositionでの再描画をトリガーするだけで、すべてが必要に応じて機能すると思います。

もちろん、矢印の位置が線の頭や尾にある場合は、updatePositionで矢印の位置を移動し、それに応じて境界ボックス/ペイントの座標を調整できます。ただし、それは意味をなさない。

+0

バウンディングボックスを変更して再描画する方法を教えてください。私は 'updatePosition'で' self.prepareGeometryChange() 'と' self.update() 'を使って試しましたが、まだ同じ動作をしています。 – pbreach

+1

それは今完璧に動作します!私が上で述べたことに加えて、 'TextBox' initに' ItemSendGeometryChanges'フラグを設定し、 'QSizeF(abs(bounds.x())、abs(bounds.y())'を 'QSizeF(bounds 'Arrow'の' boundingRect'メソッドの '.x()、bounds.y())' – pbreach

関連する問題