PyQt:如何在两个按钮之间创建lineItem并可以随按钮移动?

时间:2019-05-19 08:57:15

标签: python pyqt pyqt5

“如何在两个按钮之间创建lineItem并可以通过按钮移动”

我的程序可以使用名为“添加按钮”的按钮创建新按钮

,我想创建一个lineItem 当我单击创建的两个按钮的名为“连接”的菜单操作时。

现在,我可以在它们之间建立一条线。 但是我仍然希望它们在按钮移动时移动。

我看到一些示例是删除它并建立新行。 但我只想移动线的位置?

那行可以采取行动吗? 以下是我的代码

'In the are lines order printed reverse'

1 个答案:

答案 0 :(得分:0)

您应该更多地使用信号/插槽系统:该按钮应通知视图它想要连接,并通知其移动时间。当按钮移动时,该行应自行处理其更新。

这意味着该行已连接到按钮,按钮已连接到视图。

一个简单的例子:

当您想连接信号connectionRequested时,该按钮将发送信号moved

class DragButton(QtWidgets.QPushButton):
    connectionRequested = pyqtSignal(QtWidgets.QPushButton)
    moved = pyqtSignal()
    def __init__(self, title, parent=None):
        super().__init__(title, parent)
        self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.showMenu)

    def showMenu(self):
        menu = QtWidgets.QMenu()
        menu.addAction("connect", lambda: self.connectionRequested.emit(self))
        menu.exec_(self.cursor().pos())

    def mouseMoveEvent(self, e):
        if e.buttons() != QtCore.Qt.LeftButton:
            return
        mimeData = QtCore.QMimeData()
        drag = QtGui.QDrag(self)
        drag.setMimeData(mimeData)
        drag.setHotSpot(e.pos() - self.rect().topLeft())
        dropAction = drag.exec_(QtCore.Qt.MoveAction)

        self.moved.emit()

该行有两个参数:sourcedestination,用于在其位置之间绘制线(您可以定义pos以外的另一种方法来返回相对位置,例如您的按钮)。

class GraphicsLineItem(QtWidgets.QGraphicsLineItem):
    def __init__(self, source, destination, parent=None):
        super().__init__(parent)
        self.source = source
        self.destination = destination

        self.move()

        self.source.moved.connect(self.move)
        self.destination.moved.connect(self.move)

    def contextMenuEvent(self, event):
        menu = QtWidgets.QMenu()
        menu.addAction("Delete", self.remove)
        menu.exec_(self.cursor().pos())
        print(self.a)

    def remove(self):
        self.scene().removeItem(self)

    def shape(self):
        p = super(GraphicsLineItem, self).shape()
        stroker = QtGui.QPainterPathStroker()
        stroker.setWidth(20)
        return stroker.createStroke(p)

    def move(self):
        self.setLine(QLineF(self.source.pos(), self.destination.pos()))

当您单击第二个按钮的connect操作时,视图将创建新行。

class View(QtWidgets.QGraphicsView):
    def __init__(self, parent=None):
        super(View, self).__init__(parent)
        self.setScene(QtWidgets.QGraphicsScene(self))
        self.setAcceptDrops(True)
        self.setSceneRect(QtCore.QRectF(self.viewport().rect()))

        self.btn1 = QtWidgets.QPushButton("Start")
        self.btn1.setGeometry(230, 80, 100, 30)
        self.btn1.setCheckable(True)
        self.btn1.clicked.connect(self.add_Text)
        self.source = None


    def clearScene(self):
        self.scene().clear()
        self.source = None

    def add_Text(self):
        button = DragButton('Text', self)
        button.setGeometry(230, 80, 100, 30)
        button.show() 
        button.connectionRequested.connect(self.connectButton)

    def connectButton(self, button):
        # Do not connect a button with itself
        if not self.source or button == self.source:
            self.source = button
            return

        line = GraphicsLineItem(self.source, button)
        self.scene().addItem(line)
        self.source = None

    def dragEnterEvent(self, e):
        e.accept()

    def dragMoveEvent(self, e):
        e.accept()

    def dropEvent(self, e):
        btn = e.source()
        position = e.pos()
        btn.move(position)
        e.setDropAction(QtCore.Qt.MoveAction)
        e.accept()