2016-09-19 9 views
1

私はpyqt5を使って簡単なペイントアプリケーションに取り組んでいます。私の目標は:なぜpath.subtracted(path2)がパスをリンクしていますか?どのように私はdelinkingできますか?

です。マウスイベントに従って自由に描画します。完了しました!

。マウスイベントに従って自由に消去します。それは期待どおりの仕事ではありません!

私はQGraphicsView、QGraphicsSceneを持っています。私はQGraphicsItems、特にQGraphicsPathItemを追加しています。私の消しゴムは矩形をしていますが、私が望むのは、消しゴムを動かしながら私の作図の一部を消すことです。

MouseMoveEventで、私の消しゴムの形状が私の描画パスと交差しているかどうかを確認します。もしそうなら、描画パスから消してしまいます。そして、不自然な動作が起こり、私の描画パスが閉じます。

図1は、私の図(QGraphicsPathItem)を示しています。 図2は、私の消しゴム(QGraphicsRectItem)が私の図面と交差するときの状況を示しています。

Drawing freely lines working fine. Figure_1

Erasing drawing. Figure_2

私たちが見ることができるように、それは私の道を閉じて、私の最初と最後の点を結ぶ線を描画します。私はそれを望んでいない。私は自分の描画パスを消したいだけです。

from PyQt5.QtCore import QRectF, Qt 
from PyQt5.QtGui import QPainterPath, QPen 
from PyQt5.QtWidgets import QApplication, QGraphicsScene, \ 
    QGraphicsView, QPushButton, QWidget, \ 
    QVBoxLayout, QGraphicsItem, QGraphicsPathItem, QGraphicsRectItem 

class Window(QWidget): 
    scene = None 

    def __init__(self): 
     QWidget.__init__(self) 
     self.view = View(self) 
     self.button = QPushButton('Clear View', self) 
     self.button.clicked.connect(self.handleClearView) 
     layout = QVBoxLayout(self) 
     layout.addWidget(self.view) 
     layout.addWidget(self.button) 

    def handleClearView(self): 
     self.view.scene.clear() 


class View(QGraphicsView): 
    def __init__(self, parent): 

     self.scribing = False 
     self.erasing = False 
     QGraphicsView.__init__(self, parent) 
     self.scene = QGraphicsScene() 
     self.setScene(self.scene) 

     self.free_draw_item = None 
     self.eraser_item = None 

    def resizeEvent(self, QResizeEvent): 
     self.setSceneRect(QRectF(self.viewport().rect())) 

    def mousePressEvent(self, event): 

     if event.buttons() == Qt.LeftButton: 
      self.scribing = True 
      pp = QPainterPath(event.pos()) 

      self.free_draw_item = QGraphicsPathItem(pp) 
      self.free_draw_item.setPen(QPen(Qt.green)) 
      self.free_draw_item.setFlags(QGraphicsItem.ItemIsSelectable) 

      self.free_draw_item.setPath(pp) 
      self.scene.addItem(self.free_draw_item) 

     if event.buttons() == Qt.RightButton: 
      self.erasing = True 
      self.eraser_item = QGraphicsRectItem(event.pos().x() - 5, 
               event.pos().y() - 5, 10, 10) 
      self.eraser_item.setPen(QPen(Qt.red)) 
      self.eraser_item.setBrush(Qt.transparent) 
      self.scene.addItem(self.eraser_item) 

    def mouseMoveEvent(self, event): 

     if (event.buttons() & Qt.LeftButton) and self.scribing: 
      if self.free_draw_item: 
       path = self.free_draw_item.path() 
       path.lineTo(event.pos()) 
       self.free_draw_item.setPath(path) 

     if event.buttons() & Qt.RightButton and self.erasing: 

      self.eraser_item.setRect(event.pos().x() - 5, event.pos().y() - 5, 
            10, 10) 

      for item in self.scene.collidingItems(self.eraser_item): 
       if isinstance(item, QGraphicsPathItem): 

        if item.path().intersected(self.eraser_item.shape()): 
         new = item.path().subtracted(self.eraser_item.shape()) 
         item.setPath(new) 
         #item.setBrush(Qt.red) 

    def mouseReleaseEvent(self, event): 
     self.scribing = False 
     self.erasing = False 

     if self.eraser_item != None: 
      self.scene.removeItem(self.eraser_item) 
     # if self.free_draw_item != None: 
     #  self.free_draw_item.setSelected(True) 


if __name__ == '__main__': 
    import sys 

    app = QApplication(sys.argv) 
    window = Window() 
    window.resize(640, 480) 
    window.show() 
    sys.exit(app.exec_()) 

これは私のコードです。

マウスの左ボタンは、シーンに緑色のパスを描画します。

マウスの右ボタンで図面を消去します。

+0

箱の外に何もありません。あなたはあなたのパスをサブパスとして保持し、サブパスを変更するときにそれを再作成する必要があります。 – dtech

答えて

0

私は同じ問題を何回か繰り返しました。

この特定の問題に関するいくつかの頭痛と数千の失敗した研究の後、私は答えに来ました。

  1. は、あなたが「多くのパスを有し、かつ今の周り
  2. を作業として、あなたはすべてのサブアイテムを持っていると思うことができ、閉じた多角形
  3. にそれを回すパスを閉じずに引く傾けるだけで一つのパス
  4. を持つ忘れあなたの消しゴム
  5. に衝突したときに、「それらを削除
  6. がポイントに各パス(多角形を持って計画上の最低点)を合わせていない3と多くのパスをお持ちのあなたの好意に減算を使用し
  7. QGraphicsItemGroupとして
  8. グループそれ()あなたは、いくつかの(3ポイントパス)で作られたパス全体を操作したい場合は単一の項目
  9. として

私の例を参照してください - あなたの場合は

from PyQt5.QtCore import QPoint 
from PyQt5.QtCore import QRectF, Qt 
from PyQt5.QtGui import QBrush 
from PyQt5.QtGui import QPainter 
from PyQt5.QtGui import QPainterPath, QPen 
from PyQt5.QtWidgets import QApplication, QGraphicsScene, \ 
    QGraphicsView, QPushButton, QWidget, \ 
    QVBoxLayout, QGraphicsItem, QGraphicsPathItem, QGraphicsRectItem 
from PyQt5.QtWidgets import QGraphicsItemGroup 

from core.IQGraphicsPathItem import InteractQGraphicsPathItem 


class Window(QWidget): 
    scene = None 



    def __init__(self): 
     QWidget.__init__(self) 
     self.view = View(self) 
     self.button = QPushButton('Clear View', self) 
     self.button.clicked.connect(self.handleClearView) 
     layout = QVBoxLayout(self) 
     layout.addWidget(self.view) 
     layout.addWidget(self.button) 

    def handleClearView(self): 
     self.view.scene.clear() 


class View(QGraphicsView): 

    dic = {} 
    num_item = 0 
    _from_x_ = None 
    _from_y_ = None 
    pp = None 

    pen = None 

    group = None 

    def __init__(self, parent): 

     self.scribing = False 
     self.erasing = False 
     QGraphicsView.__init__(self, parent) 
     self.scene = QGraphicsScene() 
     self.setScene(self.scene) 
     self.setRenderHint(QPainter.Antialiasing) 
     self.free_draw_item = QGraphicsPathItem() 
     # self.free_draw_item.setPen(QPen(Qt.green)) 
     # self.free_draw_item.setFlags(QGraphicsItem.ItemIsSelectable) 
     self.eraser_item = None 
     self.pen = QPen(Qt.green,8) 
     self.pen.setBrush(QBrush(Qt.green)) 
     self.pen.setWidth(1) 

     self.group = QGraphicsItemGroup() 

    def resizeEvent(self, QResizeEvent): 
     self.setSceneRect(QRectF(self.viewport().rect())) 

    def mousePressEvent(self, event): 

     if event.buttons() == Qt.LeftButton: 
      self._from_x_ = event.pos().x() 
      self._from_y_ = event.pos().y() 

      self.scribing = True 

      self.group = QGraphicsItemGroup() 
      self.group.setFlags(QGraphicsItem.ItemIsSelectable) 
      self.scene.addItem(self.group) 

      self.pp = QPainterPath(event.pos()) 

      self.free_draw_item = QGraphicsPathItem(self.pp) 
      self.free_draw_item.setPen(self.pen) 
      # self.free_draw_item.setFlags(QGraphicsItem.ItemIsSelectable) 

      self.free_draw_item.setPath(self.pp) 
      self.scene.addItem(self.free_draw_item) 
      self.group.addToGroup(self.free_draw_item) 


     if event.buttons() == Qt.RightButton: 
      self.erasing = True 
      self.eraser_item = QGraphicsRectItem(event.pos().x() - 5, 
               event.pos().y() - 5, 10, 10) 
      self.eraser_item.setPen(QPen(Qt.red)) 
      self.eraser_item.setBrush(Qt.white) 
      self.scene.addItem(self.eraser_item) 

    def mouseMoveEvent(self, event): 

     x_adjust = 1 
     y_adjust = 1 

     # if event.pos().x() >= self._from_x_: 
     #  x_adjust = 1 
     # else: 
     #  x_adjust = -1 
     # if event.pos().y() >= self._from_y_: 
     #  y_adjust = 1 
     # else: 
     #  y_adjust = -1 



     if (event.buttons() & Qt.LeftButton) and self.scribing: 
      if self.free_draw_item: 

       # path = self.free_draw_item.path() 
       # path.lineTo(event.pos()) 
       # self.free_draw_item.setPath(path) 

       self.pp2 = QPainterPath(QPoint(self._from_x_, self._from_y_)) 
       self.pp2.lineTo(event.pos().x(), event.pos().y()) 
       self.pp2.lineTo(event.pos().x()+x_adjust, event.pos().y()+y_adjust) 
       self.pp2.lineTo(self._from_x_ + x_adjust, self._from_y_ + y_adjust) 
       self.free_draw_item.setPen(QPen(Qt.green, 8)) 
       self.free_draw_item.path = QGraphicsPathItem() 
       self.free_draw_item.path.setPath(self.pp2) 
       self.scene.addItem(self.free_draw_item.path) 
       self.group.addToGroup(self.free_draw_item) 

       self._from_x_ = event.pos().x() 
       self._from_y_ = event.pos().y() 

     if event.buttons() & Qt.RightButton and self.erasing: 

      self.eraser_item.setRect(event.pos().x() - 5, event.pos().y() - 5, 
            10, 10) 

      for item in self.scene.collidingItems(self.eraser_item): 

       new = item.path() - self.eraser_item.shape() 
       item.setPath(new) 
       print('collided') 



    def mouseReleaseEvent(self, event): 
     self.scribing = False 
     self.erasing = False 

     self.group.setSelected(True) 
     print(self.scene.items()) 

     if self.eraser_item != None: 
      self.scene.removeItem(self.eraser_item) 

     # if self.free_draw_item != None: 
     #  self.free_draw_item.setSelected(True) 


if __name__ == '__main__': 
    import sys 

    app = QApplication(sys.argv) 
    window = Window() 
    window.resize(640, 480) 
    window.show() 
    sys.exit(app.exec_()) 

あなた自身のQGraphicsPathItem()を上書きすることをお勧めします。

私はそれがかなりうまくいくと思います。

関連する問題