Перетащите 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 )
Если есть какой-то лучший способ реализовать это, пожалуйста, скажите мне.