Перетащите n Drop Button и Выпадающее меню PyQt / Qt designer

Я хотел бы знать "наилучшую практику", чтобы изменить поведение некоторых кнопок, чтобы сделать следующее:

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

Вот пример: Идея состоит в том, чтобы подключить эти кнопки «джек» к любым другим кнопкам «ввода».

Я использовал конструктор Qt и понимаю, что в свойствах кнопок указано только свойство acceptDrops, но я не могу заставить его работать. Сигналы / Слоты не перечисляют что-либо о перетаскивании.

Поэтому я думаю, что единственный способ сделать это - создать «Custom Widget» или «переопределить» кнопку за кодом. Может быть, то же самое с сигналами / слотами

Каков наилучший подход, если я не хочу изменять сгенерированный файл Pyuic?

ОБНОВИТЬ: Подход, который я попробовал, заключается в использовании Qt designer и опции «Продвигаемые виджеты». Это позволяет мне создавать отдельные файлы классов и переопределять некоторые элементы. Я уже тестировал, продвигая PushButton в DragButton и создал для него класс:

из PyQt4 импорт QtGui, QtCore

Класс DragButton (QtGui.QPushButton):

def __init__(self, parent):
     super(DragButton,  self).__init__(parent)
     self.allowDrag = True

def setAllowDrag(self, allowDrag):
    if type(allowDrag) == bool:
       self.allowDrag = allowDrag
    else:
        raise TypeError("You have to set a boolean type")

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

    if self.allowDrag == True:
        # write the relative cursor position to mime data
        mimeData = QtCore.QMimeData()
        # simple string with 'x,y'
        mimeData.setText('%d,%d' % (e.x(), e.y()))
        print mimeData.text()

        # let's make it fancy. we'll show a "ghost" of the button as we drag
        # grab the button to a pixmap
        pixmap = QtGui.QPixmap.grabWidget(self)

        # below makes the pixmap half transparent
        painter = QtGui.QPainter(pixmap)
        painter.setCompositionMode(painter.CompositionMode_DestinationIn)
        painter.fillRect(pixmap.rect(), QtGui.QColor(0, 0, 0, 127))
        painter.end()

        # make a QDrag
        drag = QtGui.QDrag(self)
        # put our MimeData
        drag.setMimeData(mimeData)
        # set its Pixmap
        drag.setPixmap(pixmap)
        # shift the Pixmap so that it coincides with the cursor position
        drag.setHotSpot(e.pos())

        # start the drag operation
        # exec_ will return the accepted action from dropEvent
        if drag.exec_(QtCore.Qt.LinkAction | QtCore.Qt.MoveAction) == QtCore.Qt.LinkAction:
            print 'linked'
        else:
            print 'moved'

def mousePressEvent(self, e):
    QtGui.QPushButton.mousePressEvent(self, e)
    if e.button() == QtCore.Qt.LeftButton:
        print 'press'
        #AQUI DEBO IMPLEMENTAR EL MENU CONTEXTUAL

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

def dropEvent(self, e):
    # get the relative position from the mime data
    mime = e.mimeData().text()
    x, y = map(int, mime.split(','))

        # move
        # so move the dragged button (i.e. event.source())
    print e.pos()
        #e.source().move(e.pos()-QtCore.QPoint(x, y))
        # set the drop action as LinkAction
    e.setDropAction(QtCore.Qt.LinkAction)
    # tell the QDrag we accepted it
    e.accept()

Я получил несколько подсказок и взял фрагменты из этого поста:PyQt4 - перетаскивание

На данный момент я могу перетащить эту кнопку и перетащить ее на другую кнопку того же типа, для которой свойство "acceptDrops" установлено в true в конструкторе Qt.Тем не менее, я все еще хочу ограничить перетаскивание некоторых кнопок (возможно, установив в главном файле с помощью метода UpdateUi), потому что некоторые будут только для принятия перетаскивания

ОБНОВЛЕНИЕ 2: Сейчас я пытаюсь написать класс, который рисует линии или «провода», соединяющие эти кнопки.

Я пытаюсь нарисовать линию между двумя виджетами (двумя кнопками) в graphicsView с их позициями в качестве ссылки. Но когда я пытаюсь, линия рисуется не в том месте. Я также пытался использовать такие функции, как mapToGlobal или mapToParent, но с разными результатами. В том же классе у меня есть другой метод, который рисует линии с помощью мыши, и работает нормально. Я воспринимал это как ссылку или пример, но, похоже, позиция событий имеет другую систему координат. Ну, я не знаю, почему это происходит.

Кнопки и графическое представление находятся внутри виджета, который также находится внутри окна.

Вот это класс, метод, о котором мы говорим, взят из PyQt4 import QtGui, QtCore

class WiringGraphicsView(QtGui.QGraphicsView):

    def __init__(self, parent):
        QtGui.QGraphicsView.__init__(self, parent)
        self.setScene(QtGui.QGraphicsScene(self))
        self.setSceneRect(QtCore.QRectF(self.viewport().rect()))

    def mousePressEvent(self, event):
        self._start = event.pos()

    def mouseReleaseEvent(self, event):
        start = QtCore.QPointF(self.mapToScene(self._start))
        end = QtCore.QPointF(self.mapToScene(event.pos()))
        brush = QtGui.QBrush(QtGui.QColor(255, 0, 0) )
        pen = QtGui.QPen(brush, 2)
        line = QtGui.QGraphicsLineItem(QtCore.QLineF(start, end))
        line.setPen(pen)
        self.scene().addItem( line )

    def paintWire(self, start_widget,  end_widget):
        start_position = QtCore.QPointF(self.mapToScene(start_widget.pos()))
        end_position = QtCore.QPointF(self.mapToScene(end_widget.pos()))
        brush = QtGui.QBrush(QtGui.QColor(255, 0, 0) )
        pen = QtGui.QPen(brush, 2)
        line = QtGui.QGraphicsLineItem(QtCore.QLineF(start_position, end_position))
        line.setPen(pen)
        self.scene().addItem( line )

Если есть какой-то лучший способ реализовать это, пожалуйста, скажите мне.

Ответы на вопрос(0)

Ваш ответ на вопрос