如何在同一个 window 上绘制两个对象?
How to draw both object on the same window?
序言:下面表示的两个对象都在同一个window。
我遇到了无法更新的问题
我遇到与 self.setGeometry(x,y,w,h)
函数相关的问题。所以我想要实现的是多个矩形,并行渲染,单击时每个矩形都有一条线突出它们的矩形。 (虽然创建连接器不是本主题的重点)。
在这种情况下,我将 rect A
和 rect B
一起渲染。 Rect A
有一条线突出到鼠标所在的位置。
(obj A) (obj B)
____ ____
| | | |
| \ | | |
---\ ----
\
(Mouse)
我要实现的目标的示例代码。
# 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)) )
但我最终得到的是 PyQt 在屏幕上显示最上面的对象,因此只显示一个对象,但是我还尝试最小化引导突出线的几何形状, 单击时,在边框上切断。
解释:
在您的情况下,它有 2 个小部件,您可以在其中绘制矩形,其中一个位于另一个之上,因此您只会看到其中一个:上面的那个。
解决方案:
Qt GraphicsView Framework(QGraphicsView、QGraphicsScene、QGraphicsXItem 等)的工作方式不同,并且不直接使用绘画,因为它们提供了实现所有功能的基本项目,因此在这种情况下,您必须将 QGraphicsRectItem 与 QGraphicsLineItem 一起使用并修改它QGraphicsView的信息。
综合以上,解决方案是:
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_())
序言:下面表示的两个对象都在同一个window。
我遇到了无法更新的问题
我遇到与 self.setGeometry(x,y,w,h)
函数相关的问题。所以我想要实现的是多个矩形,并行渲染,单击时每个矩形都有一条线突出它们的矩形。 (虽然创建连接器不是本主题的重点)。
在这种情况下,我将 rect A
和 rect B
一起渲染。 Rect A
有一条线突出到鼠标所在的位置。
(obj A) (obj B)
____ ____
| | | |
| \ | | |
---\ ----
\
(Mouse)
我要实现的目标的示例代码。
# 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)) )
但我最终得到的是 PyQt 在屏幕上显示最上面的对象,因此只显示一个对象,但是我还尝试最小化引导突出线的几何形状, 单击时,在边框上切断。
解释:
在您的情况下,它有 2 个小部件,您可以在其中绘制矩形,其中一个位于另一个之上,因此您只会看到其中一个:上面的那个。
解决方案:
Qt GraphicsView Framework(QGraphicsView、QGraphicsScene、QGraphicsXItem 等)的工作方式不同,并且不直接使用绘画,因为它们提供了实现所有功能的基本项目,因此在这种情况下,您必须将 QGraphicsRectItem 与 QGraphicsLineItem 一起使用并修改它QGraphicsView的信息。
综合以上,解决方案是:
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_())