PyQt:单击时如何在QLineItem中创建菜单

时间:2019-05-18 17:04:28

标签: python pyqt pyqt5

当我单击以下代码中的按钮时,我想创建一个菜单。 并执行“删除”之类的操作可以删除该行

我可以在QLine中这样做吗? 或菜单只能在按钮中使用...?

我想删除该行,而不是清除视图。

我尝试这个     class add_Line(QLineF):

    def __init__(self, title, parent=None):
        super().__init__(title, parent)
        menu = QMenu()
        menu.addAction = ('delete',self.deleteLater)

但不起作用 有人可以帮我吗?

import sys, os
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QDrag
from PyQt5.QtCore import Qt, QMimeData


class Window(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.view = View(self)
        self.button = QPushButton('Clear View', self)
        self.button.clicked.connect(self.handleClearView)
        layout = QVBoxLayout(self)
        layout.addWidget(self.view)
        layout.addWidget(self.button)

    def handleClearView(self):
        self.view.scene().clear()

class add_Line(QLineF):


    def __init__(self, title, parent=None):
        super().__init__(title, parent)



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

    def showMenu(self):
        menu=QMenu()
        menu.addAction('connect', self.connectLine)
        menu.exec_(self.cursor().pos())

    def connectLine(self):
        view = self.parent()
        view.createLineItem()


    def mouseMoveEvent(self, e):
        if e.buttons() != Qt.LeftButton:
            return

        mimeData = QMimeData()
        drag = QDrag(self)
        drag.setMimeData(mimeData)
        drag.setHotSpot(e.pos() - self.rect().topLeft())
        dropAction = drag.exec_(Qt.MoveAction)


class View(QGraphicsView):
    def __init__(self, parent):
        QGraphicsView.__init__(self, parent)
        self.setScene(QGraphicsScene(self))
        self.setAcceptDrops(True)
        self.setSceneRect(QtCore.QRectF(self.viewport().rect()))
        self.btn1=DragButton('Test1', self)
        self.btn2=DragButton('Test2', self)
        self.line = None

    def _createLineF(self):
        start = QtCore.QPointF(self.mapToScene(self.btn1.pos()))
        end = QtCore.QPointF(self.mapToScene(self.btn2.pos()))
        return add_Line(start,end)


    def createLineItem(self):
        self.line = QGraphicsLineItem(self._createLineF())
        self.scene().addItem(self.line)

    def clearScene(self):
        self.scene().clear()
        self.line = 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)
        if self.line:
            self.line.setLine(self._createLineF())
        e.setDropAction(Qt.MoveAction)
        e.accept()


if __name__ == '__main__':

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

2 个答案:

答案 0 :(得分:1)

QLineF仅具有线的几何信息,而不是场景中显示的项目。显示的项目是QGraphicsLineItem,并且该项目确实具有contextMenuEvent方法,因此必须在此处实现QMenu。另一方面,QGraphicsItem使用该形状指示在哪个部分接收到鼠标事件,但是默认情况下,线条的宽度很小,因此很难获得鼠标事件,因此我将形状变宽了一些使用简单:

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


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 connectLine(self):
        view = self.parent()
        view.createLineItem()

    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)


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

    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 = DragButton("Test1", self)
        self.btn2 = DragButton("Test2", self)
        self.line = None

    def _createLineF(self):
        start = QtCore.QPointF(self.mapToScene(self.btn1.pos()))
        end = QtCore.QPointF(self.mapToScene(self.btn2.pos()))
        return QtCore.QLineF(start, end)

    def createLineItem(self):
        self.line = GraphicsLineItem(self._createLineF())
        self.scene().addItem(self.line)

    def clearScene(self):
        self.scene().clear()
        self.line = 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)
        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
        )
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.view)
        layout.addWidget(self.button)


if __name__ == "__main__":

    import sys

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

答案 1 :(得分:0)

您可以考虑像为DragButton一样为订单项创建自定义窗口小部件。 然后,您可以实现相对于该订单项的上下文菜单以将其删除,就像对“ DragButton”的“连接”操作所做的一样。