2016-09-19 29 views
1

我正在使用pyqt5編寫一個簡單的Paint應用程序。我的目標是:爲什麼path.subtracted(path2)正在鏈接我的路徑?我怎樣才能脫鉤?

。根據鼠標事件自由繪製。完成!

。根據鼠標事件自由擦除。它沒有按預期工作!

我有一個QGraphicsView,QGraphicsScene,我添加QGraphicsItems,特別是QGraphicsPathItem。我的橡皮擦具有矩形形狀,我想要的是在移動橡皮擦的同時擦除部分圖形。

在MouseMoveEvent上,我檢查橡皮擦的形狀是否與我的繪圖路徑相交,如果是這樣,我只是從我的繪圖路徑中減去它。然後發生尷尬的行爲,它關閉我的繪圖路徑。

figure_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分路)查看我的例子

-

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()。

我認爲它會工作得很好。