I am trying to paint on a QPixmap inside a QGraphicsView. The painting works fine, but the QGraphicsView doesn't update it.
Here is some working code:
#!/usr/bin/env python
from PyQt4 import QtCore
from PyQt4 import QtGui
class Canvas(QtGui.QPixmap):
""" Canvas for drawing"""
def __init__(self, parent=None):
QtGui.QPixmap.__init__(self, 64, 64)
self.parent = parent
self.imH = 64
self.imW = 64
self.fill(QtGui.QColor(0, 255, 255))
self.color = QtGui.QColor(0, 0, 0)
def paintEvent(self, point=False):
if point:
p = QtGui.QPainter(self)
p.setPen(QtGui.QPen(self.color, 1, QtCore.Qt.SolidLine))
p.drawPoints(point)
def clic(self, mouseX, mouseY):
self.paintEvent(QtCore.QPoint(mouseX, mouseY))
class GraphWidget(QtGui.QGraphicsView):
""" Display, zoom, pan..."""
def __init__(self):
QtGui.QGraphicsView.__init__(self)
self.im = Canvas(self)
self.imH = self.im.height()
self.imW = self.im.width()
self.zoomN = 1
self.scene = QtGui.QGraphicsScene(self)
self.scene.setItemIndexMethod(QtGui.QGraphicsScene.NoIndex)
self.scene.setSceneRect(0, 0, self.imW, self.imH)
self.scene.addPixmap(self.im)
self.setScene(self.scene)
self.setTransformationAnchor(QtGui.QGraphicsView.AnchorUnderMouse)
self.setResizeAnchor(QtGui.QGraphicsView.AnchorViewCenter)
self.setMinimumSize(400, 400)
self.setWindowTitle("pix")
def mousePressEvent(self, event):
if event.buttons() == QtCore.Qt.LeftButton:
pos = self.mapToScene(event.pos())
self.im.clic(pos.x(), pos.y())
#~ self.scene.update(0,0,64,64)
#~ self.updateScene([QtCore.QRectF(0,0,64,64)])
self.scene.addPixmap(self.im)
print('items')
print(self.scene.items())
else:
return QtGui.QGraphicsView.mousePressEvent(self, event)
def wheelEvent(self, event):
if event.delta() > 0:
self.scaleView(2)
elif event.delta() < 0:
self.scaleView(0.5)
def scaleView(self, factor):
n = self.zoomN * factor
if n < 1 or n > 16:
return
self.zoomN = n
self.scale(factor, factor)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
widget = GraphWidget()
widget.show()
sys.exit(app.exec_())
The mousePressEvent does some painting on the QPixmap. But the only solution I have found to update the display is to make a new instance (which is not a good solution).
How do I just update it?
The pixmap can't be linked to your scene, the item uses an internal copy of it, so you have to update the QGraphicsPixmapItem with the new pixmap:
def __init__(self):
...
# save the item as a member
self.imItem = self.scene.addPixmap(self.im)
...
def mousePressEvent(self, event):
if event.buttons() == QtCore.Qt.LeftButton:
pos = self.mapToScene(event.pos())
self.im.clic(pos.x(), pos.y())
self.imItem.setPïxmap(self.im)
...
But it would make more sense to make your class Canvas inherit from QGraphicsPixmapItem instead of QPixmap, you would still have to get the pixmap with pixmap(), paint on it, and call setPixmap to update it. As a bonus, that code would be in the item own mousePressEvent method.
Related
I am designing an app to draw electrical circuit models and I need to insert elements on scene by clicking on a button and after on the scene.
The way it should work is the following: I press the button to insert a node, then it shows a message saying "Press where you want to insert the element", you press, and the element appear on screen.
I think the problem is that I have to stop the code to get the position and then continue or something like that.
Below I show a part of the code (the original contains more classes and a second tab for calculations, that it is not needed for this trouble and it is not connected in any way):
from PyQt5 import sip
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import QRectF, Qt, QSize, QPointF, QPoint, QLineF, showbase
from PIL import Image
import calculation
class Main(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Nodal Equations")
self.setWindowIcon(QIcon("images/flash.ico"))
self.setGeometry(150,50,1650,950)
self.setFixedSize(self.size())
self.UI()
self.show()
def UI(self):
self.toolBar()
self.tabwidgets()
self.widgets()
self.layouts()
def toolBar(self):
self.tb = QToolBar("Toolbar")
self.addToolBar(Qt.RightToolBarArea, self.tb)
self.tb.setIconSize(QSize(50,50))
# Toolbar buttons
self.addNode = QAction(QIcon("images/node.png"),"Node",self)
self.tb.addAction(self.addNode)
self.addNode.triggered.connect(self.funcAddNode)
self.tb.addSeparator()
def tabwidgets(self):
self.tabs = QTabWidget()
self.tabs.blockSignals(True) # To update tabs. After defining every layout we have to set it to False
self.setCentralWidget(self.tabs) # If this is not used, we cannot see the widgets (Needed if we use QMainWindow)
self.modelViewTab = QWidget()
self.tabs.addTab(self.modelViewTab, "Model View")
def widgets(self):
# Model View widgets
self.view = ModelView()
self.instructionsLabel = QLabel("Welcome to Node Equations Solver. To start select an order on the toolbar menu", self)
def layouts(self):
# Model View Tab layouts
self.mainModelLayout = QVBoxLayout()
self.sceneLayout = QHBoxLayout()
self.instructionsLayout = QHBoxLayout()
self.mainModelLayout.setAlignment(Qt.AlignCenter)
##### Adding widgets
self.sceneLayout.addWidget(self.view)
self.instructionsLayout.addWidget(self.instructionsLabel)
##### Adding layouts
self.mainModelLayout.addLayout(self.sceneLayout)
self.mainModelLayout.addLayout(self.instructionsLayout)
self.modelViewTab.setLayout(self.mainModelLayout)
def funcAddNode(self):
self.node = Node(0,500,500)
self.view.scene.addItem(self.node)
class Node(QGraphicsEllipseItem):
def __init__(self,number, x, y):
super(Node, self).__init__(0, 0, 10, 10)
self.number = number
self.setPos(x, y)
self.setBrush(Qt.yellow)
self.setAcceptHoverEvents(True)
# Mouse hover events
def hoverEnterEvent(self, event):
app.instance().setOverrideCursor(Qt.OpenHandCursor)
def hoverLeaveEvent(self, event):
app.instance().restoreOverrideCursor()
# Mouse click events
def mousePressEvent(self, event):
app.instance().setOverrideCursor(Qt.ClosedHandCursor)
def mouseReleaseEvent(self, event):
app.instance().restoreOverrideCursor()
def mouseMoveEvent(self, event):
orig_cursor_position = event.lastScenePos()
updated_cursor_position = event.scenePos()
orig_position = self.scenePos()
updated_cursor_x = updated_cursor_position.x() - orig_cursor_position.x() + orig_position.x()
updated_cursor_y = updated_cursor_position.y() - orig_cursor_position.y() + orig_position.y()
if updated_cursor_x < 0:
self.setPos(QPointF(0, updated_cursor_y))
elif updated_cursor_y < 0:
self.setPos(QPointF(updated_cursor_x, 0))
elif updated_cursor_x + self.boundingRect().right() > 1550:
self.setPos(QPointF(1550 - self.boundingRect().width(), updated_cursor_y))
elif updated_cursor_y + self.boundingRect().bottom() > 840:
self.setPos(QPointF(updated_cursor_x, 840 - self.boundingRect().height()))
else:
self.setPos(QPointF(updated_cursor_x, updated_cursor_y))
class ModelView(QGraphicsView):
def __init__(self):
super().__init__()
self.setRenderHints(QPainter.Antialiasing)
self.scene = QGraphicsScene()
self.setScene(self.scene)
self.setSceneRect(0, 0, 1550, 840)
##### This is a way I tried to pick the cursor position and store it, but it didn't work
# def mousePressEvent(self, event):
# x = event.scenePos().x()
# y = event.scenePos().y()
# return (x,y)
def main():
global app
app = QApplication(sys.argv)
window = Main()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
You need to change the return (x,y) to something useful, i.e. emitting a signal or actually adding an element.
mousePressEvent is a method that does not return anything (void in C++).
I have the two classes below. The Crop class is an example of code I found in the web for draw rectangles on images by click and drag. It's perfect for use with some modifications, for cropping parts of images. Originanlly it was a autonomous program, but now I Intended to use it together a MainClass, as a tool for capturing parts of images.
The images would be added to a QGraphicView widget generated by the MainClass, so the Crop class has to be able to access this widget. The widget, I named "Image_crop_screen.ui" was created using Qt Designer. It's a MainWindow with size 800 x 800 pixels, containing a Graphics View also 800 x 800 pixels in size.
Until now, I haven't been able to make Crop class work togther MainClass. I tried to call Crop(self). The MainWindow opens but it seems the click events is not detected.
(Sorry the bad English it's not my native language).
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5 import uic
CROP_UI = uic.loadUiType("Image_crop_screen.ui")[0]
class MainClass(QMainWindow, CROP_UI):
def __init__(self):
super().__init__()
self.setupUi(self)
# Graphic Screen set
pixmap = QPixmap('')
self.img = QGraphicsPixmapItem(pixmap)
self.scene = QGraphicsScene()
self.scene.addItem(self.img)
self.graphicsView.setScene(self.scene)
Crop(self) # Here I tried access the class Crop
class Crop(QMainWindow):
def __init__(self, main):
super(Crop, self).__init__()
self.main = main
self.main.graphicsView.viewport().installEventFilter(self)
self.current_item = None
self.start_pos = QPointF()
self.end_pos = QPointF()
def eventFilter(self, o, e):
if self.main.graphicsView.viewport() is o:
if e.type() == QEvent.MouseButtonPress:
if e.buttons() & Qt.LeftButton:
self.start_pos = self.end_pos = self.main.graphicsView.mapToScene(e.pos())
pen = QPen(QColor(255, 0, 0))
pen.setWidth(1)
brush = QBrush(QColor(0, 0, 0, 0))
self.current_item = self.scene.addRect(QRectF(), pen, brush)
self._update_item()
elif e.type() == QEvent.MouseMove:
if e.buttons() & Qt.LeftButton and self.current_item is not None:
self.end_pos = self.main.graphicsView.mapToScene(e.pos())
self._update_item()
elif e.type() == QEvent.MouseButtonRelease:
self.end_pos = self.main.graphicsView.mapToScene(e.pos())
self._update_item()
self.current_item = None
return super().eventFilter(o, e)
def _update_item(self):
if self.current_item is not None:
self.current_item.setRect(QRectF(self.start_pos, self.end_pos).normalized())
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainClass()
main.show()
app.exec_()
I'm new to Qt, and specially to PyQt5. I'm trying to develop a GUI using QGraphicsView, QGraphicsScene and QGraphicsPixmapItem. My objective is to add items to the scene when the user clicks on the scene (achieved using mousePressedEvent() in a QGraphicsScene subclass) and, using mouseMoveEvent(), I was able to move the element.
Then, I discovered that, with my implementation, the items could be moved like "pushing" them from outside the bounding rect. So, in order to fix it, after some searching, I decided to implement a subclass of QGraphicsPixmapItem to implement its own event functions.
Nevertheless, I found out that my item does not recognize mousePressed nor mouseMove events, but the ones from QGraphicsScene. My questions are:
What is the most efficient way to move elements without having the first problem I encountered?
Is it possible to combine both scene and item event handlers? I have not understood event propagation completely.
To make it more clear, I leave my code down below for the moving problem:
#!/usr/bin/env python3
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
class GraphicsScene(QGraphicsScene):
def __init__(self):
super(GraphicsScene, self).__init__()
self.image = 'car.png' # Image of your own
self.inserted = False
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton and not self.inserted:
img = QPixmap(self.image).scaled(50, 50, Qt.KeepAspectRatio)
pixmap = QGraphicsPixmapItem(img)
offset = pixmap.boundingRect().topLeft() - pixmap.boundingRect().center()
pixmap.setOffset(offset.x(), offset.y())
pixmap.setShapeMode(QGraphicsPixmapItem.BoundingRectShape)
pixmap.setFlag(QGraphicsItem.ItemIsSelectable, True)
pixmap.setPos(event.scenePos())
super().mousePressEvent(event)
self.addItem(pixmap)
self.inserted = True
else:
pass
def mouseMoveEvent(self, event):
super().mouseMoveEvent(event)
item = self.itemAt(event.scenePos(), QTransform())
if item is None:
return
orig_cursor_position = event.lastScenePos()
updated_cursor_position = event.scenePos()
orig_position = item.scenePos()
updated_cursor_x = updated_cursor_position.x() - orig_cursor_position.x() + orig_position.x()
updated_cursor_y = updated_cursor_position.y() - orig_cursor_position.y() + orig_position.y()
item.setPos(QPointF(updated_cursor_x, updated_cursor_y))
class MainWindow(QMainWindow):
def __init__(self):
super(QMainWindow, self).__init__()
self.resize(600, 600)
self.canvas = QGraphicsView()
self.scene = GraphicsScene()
self.setCentralWidget(self.canvas)
self.canvas.setScene(self.scene)
def showEvent(self, event):
self.canvas.setSceneRect(QRectF(self.canvas.viewport().rect()))
def resizeEvent(self, event):
self.canvas.setSceneRect(QRectF(self.canvas.viewport().rect()))
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
I think that the OP is unnecessarily complicated since the QGraphicsItems (like QGraphicsPixmapItem) already implement this functionality and it only remains to activate the QGraphicsItem::ItemIsMovable flag:
class GraphicsScene(QGraphicsScene):
def __init__(self):
super(GraphicsScene, self).__init__()
self.image = "car.png" # Image of your own
self.inserted = False
def mousePressEvent(self, event):
super().mousePressEvent(event)
if event.button() == Qt.LeftButton and not self.inserted:
img = QPixmap(self.image).scaled(50, 50, Qt.KeepAspectRatio)
pixmap = QGraphicsPixmapItem(img)
pixmap.setOffset(-pixmap.boundingRect().center())
pixmap.setShapeMode(QGraphicsPixmapItem.BoundingRectShape)
pixmap.setFlag(QGraphicsItem.ItemIsSelectable, True)
pixmap.setFlag(QGraphicsItem.ItemIsMovable, True)
pixmap.setPos(event.scenePos())
self.addItem(pixmap)
self.inserted = True
Override mouseMoveEvent is unnecessary.
My code is drawing lines on a QImage using mousePressEvent and mouseReleaseEvent. It works fine but I would like a dynamic preview line to appear when I'm drawing the said line (ie on MouseMoveEvent). Right now the line just appears when I release the left mouse button and I can't see what I'm drawing.
I want the preview of the line to appear and update as I move my mouse, and only "fixate" when I release the left mouse button. Exactly like the MS Paint Line tool : https://youtu.be/YIw9ybdoM6o?t=207
Here is my code (it is derived from the Scribble Example):
from PyQt5.QtCore import QPoint, QRect, QSize, Qt
from PyQt5.QtGui import QImage, QPainter, QPen, QColor, qRgb
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow
import sys
class DrawingArea(QWidget):
def __init__(self, parent=None):
super(DrawingArea, self).__init__(parent)
self.setAttribute(Qt.WA_StaticContents)
self.scribbling = False
self.myPenWidth = 1
self.myPenColor = QColor('#000000')
self.image = QImage()
self.startPoint = QPoint()
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.startPoint = event.pos()
self.scribbling = True
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton and self.scribbling:
self.drawLineTo(event.pos())
self.scribbling = False
def paintEvent(self, event):
painter = QPainter(self)
dirtyRect = event.rect()
painter.drawImage(dirtyRect, self.image, dirtyRect)
def resizeEvent(self, event):
if self.width() > self.image.width() or self.height() > self.image.height():
newWidth = max(self.width() + 128, self.image.width())
newHeight = max(self.height() + 128, self.image.height())
self.resizeImage(self.image, QSize(newWidth, newHeight))
self.update()
super(DrawingArea, self).resizeEvent(event)
def drawLineTo(self, endPoint):
painter = QPainter(self.image)
painter.setPen(QPen(self.myPenColor, self.myPenWidth, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
painter.drawLine(self.startPoint, endPoint)
rad = self.myPenWidth / 2 + 2
self.update(QRect(self.startPoint, endPoint).normalized().adjusted(-rad, -rad, +rad, +rad))
def resizeImage(self, image, newSize):
if image.size() == newSize:
return
newImage = QImage(newSize, QImage.Format_RGB32)
newImage.fill(qRgb(255, 255, 255))
painter = QPainter(newImage)
painter.drawImage(QPoint(0, 0), image)
self.image = newImage
class MainWindow(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.setCentralWidget(DrawingArea())
self.show()
def main():
app = QApplication(sys.argv)
ex = MainWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I can't figure out how to show the preview of the line I'm drawing and I haven't found a suitable answer yet. How can I go about doing this ?
You can draw the lines just within the paintEvent() method instead than directly on the image, then paint on the image when the mouse is actually released.
class DrawingArea(QWidget):
def __init__(self, parent=None):
super(DrawingArea, self).__init__(parent)
self.setAttribute(Qt.WA_StaticContents)
self.scribbling = False
self.myPenWidth = 1
self.myPenColor = QColor('#000000')
self.image = QImage()
self.startPoint = self.endPoint = None
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.startPoint = event.pos()
def mouseMoveEvent(self, event):
if self.startPoint:
self.endPoint = event.pos()
self.update()
def mouseReleaseEvent(self, event):
if self.startPoint and self.endPoint:
self.updateImage()
def paintEvent(self, event):
painter = QPainter(self)
dirtyRect = event.rect()
painter.drawImage(dirtyRect, self.image, dirtyRect)
if self.startPoint and self.endPoint:
painter.drawLine(self.startPoint, self.endPoint)
def updateImage(self):
if self.startPoint and self.endPoint:
painter = QPainter(self.image)
painter.setPen(QPen(self.myPenColor, self.myPenWidth, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
painter.drawLine(self.startPoint, self.endPoint)
painter.end()
self.startPoint = self.endPoint = None
self.update()
Note that you don't need to call update() within the resize event, as it's automatically called.
I also removed the unnecessary update rect calls, as it's almost useless in this case: specifying a rectangle in which the update should happen is usually done when very complex widgets are drawn (especially when lots of computations are executed to correctly draw everything and only a small part of the widget actually needs updates). In your case, it's almost more time consuming to compute the actual update rectangle than painting all the contents of the widget.
I think this page shows some really nice solutions for the problem of yours. For example, it shows how to implement a custom class which actually gives you a "drawing board":
class Canvas(QLabel):
def __init__(self):
super().__init__()
pixmap = QtGui.QPixmap(600, 300)
self.setPixmap(pixmap)
self.last_x, self.last_y = None, None
self.pen_color = QtGui.QColor('#000000')
def set_pen_color(self, c):
self.pen_color = QtGui.QColor(c)
def mouseMoveEvent(self, e):
if self.last_x is None: # First event.
self.last_x = e.x()
self.last_y = e.y()
return # Ignore the first time.
painter = QtGui.QPainter(self.pixmap())
p = painter.pen()
p.setWidth(1)
p.setColor(self.pen_color)
painter.setPen(p)
painter.drawLine(self.last_x, self.last_y, e.x(), e.y())
painter.end()
self.update()
# Update the origin for next time.
self.last_x = e.x()
self.last_y = e.y()
def mouseReleaseEvent(self, e):
self.last_x = None
self.last_y = None
You can use this Canvas class (or whatever name you would give it) everywhere you need. For example in the MainWindow:
class MainWindow(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.canvas = Canvas()
self.canvas.set_pen_color('#fffee5') # set the colour you want
self.setCentralWidget(self.canvas)
self.show()
Hope this could help! Happy coding! :)
Prologue: Both of the object represented below are on the same window.
I am having problem with the not updating
I am having a problem related to self.setGeometry(x,y,w,h) function. So what I want to achieve is multiple rect, rendered in parallel, which each has a line protruding out of their rectangle when clicked. (Creating a connector though that is not the point of this topic).
In this case, I have rect A and rect B rendering together. Rect A has a line protruding out to the position of the mouse.
(obj A) (obj B)
____ ____
| | | |
| \ | | |
---\ ----
\
(Mouse)
An example code of what am I trying to achieve.
# File: connectors.py
from PyQt5.QtCore import Qt, QPoint
from PyQt5.QtGui import QPainter
from PyQt5.QtWidgets import QWidget
class Connector(QWidget):
def __init__(self, rect: List[int]):
super().__init__()
self.setGeometry(0, 0, 1920, 1080)
self.rect = rect
self.clicked = False
self.begin = QPoint(rect[0], rect[1])
self.end = QPoint(0,0)
def paintEvent(self, event):
qp = QPainter()
qp.begin(self)
qp.setPen(Qt.red)
qp.drawRect(*self.rect)
if self.clicked:
qp = QPainter()
qp.begin(self)
qp.setPen(Qt.red)
qp.drawLine(self.begin, self.end)
self.update()
def mousePressEvent(self, event):
if event.button() == 1:
self.clicked = True
self.end = event.pos()
def mouseMoveEvent(self, event):
if self.clicked:
self.end = event.pos()
def mouseReleaseEvent(self, event):
if event.button() == 1:
self.clicked = False
self.end = event.pos()
# File: main.py
scene = QGraphicsScene()
scene.addWidget( Connector((400, 400, 100, 100)) )
scene.addWidget( Connector((400, 600, 100, 100)) )
But what I am ending up is PyQt showing the top-most object onto the screen thus only showing one object, BUT I also tried to minimize the geometry leading the protruding line, when clicked, cutting off on the border.
Explanation:
In your case it has 2 widgets where you draw the rectangles where one is on top of another so you will only see one of them: the one above.
Solution:
Qt GraphicsView Framework (QGraphicsView, QGraphicsScene, QGraphicsXItem, etc.) works differently and painting is not used directly since they offer basic items that implement all the functionalities so in this case you must use QGraphicsRectItem with QGraphicsLineItem and modify it with the information of the QGraphicsView.
Considering the above, the solution is:
import sys
from PyQt5.QtCore import QRectF, Qt
from PyQt5.QtWidgets import (
QApplication,
QGraphicsLineItem,
QGraphicsRectItem,
QGraphicsScene,
QGraphicsView,
)
class RectItem(QGraphicsRectItem):
def __init__(self, rect, parent=None):
super().__init__(parent)
self.setRect(QRectF(*rect))
self.setPen(Qt.red)
self._line_item = QGraphicsLineItem(self)
self.line_item.setPen(Qt.red)
l = self.line_item.line()
l.setP1(self.rect().topLeft())
l.setP2(self.rect().topLeft())
self.line_item.setLine(l)
self.line_item.hide()
#property
def line_item(self):
return self._line_item
def move_line_to(self, sp):
lp = self.mapFromScene(sp)
l = self.line_item.line()
l.setP2(lp)
self.line_item.setLine(l)
class GraphicsView(QGraphicsView):
def __init__(self, parent=None):
super().__init__(parent)
self.setScene(QGraphicsScene())
self.scene().addItem(RectItem((400, 400, 100, 100)))
self.scene().addItem(RectItem((400, 600, 100, 100)))
def mousePressEvent(self, event):
vp = event.pos()
sp = self.mapToScene(vp)
self.move_lines(sp)
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
vp = event.pos()
sp = self.mapToScene(vp)
self.move_lines(sp)
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
for item in self.items():
if isinstance(item, RectItem):
item.line_item.hide()
super().mouseReleaseEvent(event)
def move_lines(self, sp):
for item in self.items():
if isinstance(item, RectItem):
item.line_item.show()
item.move_line_to(sp)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = GraphicsView()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())