PyQt: как создать меню в QLineItem, когда я щелкаю по нему - PullRequest
2 голосов
/ 18 мая 2019

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

Могу ли я сделать это в QLine? или меню просто можно использовать в кнопке ...?

и я хочу удалить строку, а не очистить вид.

Я пытаюсь это класс 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 ]

1 голос
/ 18 мая 2019

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_())
0 голосов
/ 18 мая 2019

Возможно, вы захотите создать собственный виджет для своей позиции, как вы это делали для DragButton.Затем вы можете реализовать контекстное меню относительно этого элемента строки, чтобы удалить его, так же, как вы делали это для действия «connect» для DragButton.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...