PyQt: Как создать lineItem между двумя кнопками и можно перемещать с помощью кнопки? - PullRequest
1 голос
/ 19 мая 2019

"Как создать элемент line между двумя кнопками и можно перемещать с помощью кнопки"

моя программа может создать новую кнопку с кнопкой «Добавить кнопку»

и я хочу создать строку элемента когда я щелкаю созданное меню действие с двумя кнопками с именем «connect».

Теперь я могу построить линию между ними. но я все еще хочу, чтобы они двигались, когда кнопка перемещается.

Я вижу, например, удалить его и построить новую строку .. но я хочу просто переместить позицию линии?

Может ли линия выполнить это действие? ниже мой код

import sys, os
from PyQt5 import QtCore, QtGui, QtWidgets



can_draw=0
start=0
end=0
first_connect=0
second_connect =0


class DragButton(QtWidgets.QPushButton):
    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", self.connectLine)
        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)


    def connectLine(self):

        global can_draw
        global start
        global end
        global first_connect
        global second_connect 

        view = self.parent()

        can_draw +=1

        if can_draw == 1:


            start = QtCore.QPointF(view.mapToScene(self.pos()))


        if can_draw == 2:

            end = QtCore.QPointF(view.mapToScene(self.pos()))


            can_draw -= 2


            view.createLineItem(start,end)

class GraphicsLineItem(QtWidgets.QGraphicsLineItem):



    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)


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.line = None

    def _createLineF(self,start,end):

        return QtCore.QLineF(start, end)

    def createLineItem(self,start,end):

        self.line = GraphicsLineItem(self._createLineF(start,end))
        self.scene().addItem(self.line)


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

    def add_Text(self):

        self.button = DragButton('Text', self)
        self.button.setGeometry(230, 80, 100, 30)

        self.button.show() 



    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)
        if self.line:
            self.line.setLine(self._createLineF())
        e.setDropAction(QtCore.Qt.MoveAction)
        e.accept()


class Window(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        self.view = View()
        self.button = QtWidgets.QPushButton(
            "Clear View", clicked=self.view.scene().clear
        )
        self.btn1 = QtWidgets.QPushButton("add button")
        self.btn1.setCheckable(True)
        self.btn1.clicked.connect(self.view.add_Text)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.view)
        layout.addWidget(self.btn1)


if __name__ == "__main__":

    import sys

    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.resize(640, 480)
    window.show()
    sys.exit(app.exec_())

1 Ответ

0 голосов
/ 20 мая 2019

Вам следует больше использовать систему «сигнал / слот»: кнопка должна уведомить представление о том, что она хочет подключиться, и уведомить, когда она движется. Линия должна обрабатывать свои обновления, когда кнопка перемещается.

Это означает, что линия связана с кнопкой, а кнопка с видом.

Быстрый пример:

Кнопка отправит сигнал 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()

Линия имеет два параметра: source и destination, которые используются для рисования линии между их позициями (вы можете определить другой метод, чем 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...