我目前正在使用PyQt5和Graphicscene构建一个交互式画布,目前修改了这些帖子中的代码。
我已经做了两个单独的例子,我想,但到目前为止,我还没有能够将两个合并成一个单一的代码。
第一段代码我在屏幕上点击的位置插入一个节点和相应的边缘。以鼠标左键双击开始和结束。
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import *
class WindowClass(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.view = ViewClass()
self.setCentralWidget(self.view)
class ViewClass(QGraphicsView):
def __init__(self, parent=None):
QGraphicsView.__init__(self, parent)
self.s = SceneClass()
self.setScene(self.s)
self.setRenderHint(QPainter.Antialiasing)
class SceneClass(QGraphicsScene):
def __init__(self, parent=None):
QGraphicsScene.__init__(self, QRectF(-1000, -1000, 2000, 2000), parent)
self.node_start = None
self.node_end = None
self.pos = None
self.pos_end = None
def mouseDoubleClickEvent(self, event):
if event.button() == Qt.LeftButton and self.node_start is None:
node = Node()
self.addItem(node)
node.setPos(event.scenePos() + QPointF(10, 10))
self.node_start = node
else:
self.node_start = None
def mouseMoveEvent(self, event):
super(SceneClass, self).mouseMoveEvent(event)
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton and self.node_start:
"nodo final"
node = Node()
self.addItem(node)
node.setPos(event.scenePos() + QPointF(10, 10))
self.node_end = node
edge = Edge(self.node_start, self.node_end)
self.addItem(edge)
"nodo final se convierte en nodo inicial"
self.node_start = self.node_end
super(SceneClass, self).mousePressEvent(event)
class Node(QGraphicsEllipseItem):
def __init__(self, rect=QRectF(-20, -20, 20, 20), parent=None):
QGraphicsEllipseItem.__init__(self, rect, parent)
self.edges = []
self.setZValue(1)
self.setBrush(Qt.darkGray)
self.setFlag(QGraphicsItem.ItemIsMovable, True)
self.setFlag(QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
def addEdge(self, edge):
self.edges.append(edge)
def itemChange(self, change, value):
if change == QGraphicsItem.ItemSelectedChange:
self.setBrush(Qt.green if value else Qt.darkGray)
if change == QGraphicsItem.ItemPositionHasChanged:
for edge in self.edges:
edge.adjust()
return QGraphicsItem.itemChange(self, change, value)
class Edge(QGraphicsLineItem):
def __init__(self, source, dest, parent=None):
QGraphicsLineItem.__init__(self, parent)
self.source = source
self.dest = dest
self.source.addEdge(self)
self.dest.addEdge(self)
self.setPen(QPen(Qt.red, 3))
self.adjust()
def adjust(self):
self.prepareGeometryChange()
self.setLine(QLineF(self.dest.pos() + QPointF(-10, -10), self.source.pos() + QPointF(-10, -10)))
if __name__ == '__main__':
app = QApplication(sys.argv)
wd = WindowClass()
wd.show()
sys.exit(app.exec_())
第二段代码从最后点击鼠标左键的位置到当前鼠标在屏幕上的位置画一条线。
import sys
from PyQt5.QtWidgets import (QApplication, QLabel, QWidget)
from PyQt5.QtGui import QPainter, QColor, QPen
from PyQt5.QtCore import Qt
class MouseTracker(QWidget):
def __init__(self):
super().__init__()
self.initUI()
self.setMouseTracking(True)
def initUI(self):
self.setGeometry(200, 200, 1000, 500)
self.setWindowTitle('Mouse Tracker')
self.label = QLabel(self)
self.label.resize(500, 40)
self.show()
self.pos = None
self.pos_end = None
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.pos_end = event.pos()
def mouseMoveEvent(self, event):
self.pos = event.pos()
self.update()
def paintEvent(self, event):
if self.pos and self.pos_end:
"Estilo de Linea"
pen = QPen(Qt.red)
pen.setWidth(3)
pen.setStyle(Qt.CustomDashLine)
pen.setDashPattern([10, 10])
pen.setJoinStyle(Qt.RoundJoin)
"Objeto de QPainter"
q = QPainter(self)
q.setRenderHint(QPainter.Antialiasing, True)
"Aplicar estilo de Linea"
q.setPen(pen)
"Dibujar Linea"
q.drawLine(self.pos.x(), self.pos.y(), self.pos_end.x(), self.pos_end.y())
app = QApplication(sys.argv)
ex = MouseTracker()
sys.exit(app.exec_())
我希望在mi GUI代码中看到的行为是这两个代码的结合,意思是:能够通过鼠标左键插入节点及其对应的边缘,然后当鼠标左键被释放时,从最后插入的节点到屏幕上的当前位置开始第二段代码的QPaint线。我试着把这两段代码连接起来,但是当第一段代码的任何一个类被写入时,paintvent没有被触发,即使ti是自己的类。
QPainter是用来作画的低级工具,不同的高级工具都用它作为Qt图形框架,但在这种情况下不应该使用它们。
在你的情况下,最好使用这些项目,因为它简化了任务。
class WindowClass(QMainWindow):
def __init__(self, parent=None):
super(WindowClass, self).__init__(parent)
view = QGraphicsView()
view.setMouseTracking(True)
view.setRenderHint(QPainter.Antialiasing)
scene = SceneClass(self)
view.setScene(scene)
self.setCentralWidget(view)
self.resize(640, 480)
class SceneClass(QGraphicsScene):
def __init__(self, parent=None):
super(SceneClass, self).__init__(QRectF(-1000, -1000, 2000, 2000), parent)
self._edge_item = None
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
node = Node()
node.setPos(event.scenePos())
self.addItem(node)
if self._edge_item:
self._edge_item.dst = node
self._edge_item = None
else:
self._edge_item = Edge()
self._edge_item.src = node
self.addItem(self._edge_item)
def mouseMoveEvent(self, event):
if self._edge_item:
self._edge_item.p2 = event.scenePos()
super(SceneClass, self).mouseMoveEvent(event)
class Node(QGraphicsEllipseItem):
def __init__(self, rect=QRectF(-10, -10, 20, 20), parent=None):
super(Node, self).__init__(rect, parent)
self.edges = []
self.setZValue(1)
self.setBrush(Qt.darkGray)
self.setFlag(QGraphicsItem.ItemIsMovable, True)
self.setFlag(QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
def addEdge(self, edge):
self.edges.append(edge)
def itemChange(self, change, value):
if change == QGraphicsItem.ItemSelectedChange:
self.setBrush(Qt.green if value else Qt.darkGray)
if change == QGraphicsItem.ItemPositionHasChanged:
for edge in self.edges:
edge.adjust()
return super(Node, self).itemChange(change, value)
class Edge(QGraphicsLineItem):
def __init__(self, parent=None):
super(Edge, self).__init__(parent)
self.setPen(QPen(Qt.red, 3))
self._src = None
self._dst = None
@property
def src(self):
return self._src
@src.setter
def src(self, node):
self._src = node
self._src.addEdge(self)
self.adjust()
@property
def dst(self):
return self._dst
@dst.setter
def dst(self, node):
self._dst = node
self._dst.addEdge(self)
self.adjust()
@property
def p1(self):
return self.line().p1()
@p1.setter
def p1(self, p):
line = self.line()
line.setP1(p)
self.setLine(line)
@property
def p2(self):
return self.line().p2()
@p2.setter
def p2(self, p):
line = self.line()
line.setP2(p)
self.setLine(line)
def adjust(self):
self.prepareGeometryChange()
if self.src:
self.p1 = self.src.pos()
self.p2 = self.src.pos()
if self.dst:
self.p2 = self.dst.pos()