我想了解如何改变一些按钮的行为才能实现以下功能:
我希望点击一下就会弹出一个菜单。或者当你拖动同一个按钮并将其放入另一个按钮中时,它们之间会“连线”。
这是一个示例:
这个想法是将那些“插孔”按钮与任何其他“输入”按钮连接起来。
我使用 Qt Designer,发现只有接受拖放属性列在按钮属性中,但我无法使其工作。 信号/插槽没有关于拖放的信息。
所以我认为唯一的方法是通过代码创建“自定义小部件”或“重新实现”按钮。也许通过信号/插槽可以实现相同的功能。
如果我不想修改 pyuic 生成的文件,最好的方法是什么?
更新:我尝试使用Qt Designer和“Promoted widgets”选项来实现。这使我可以创建独立的类文件并重新实现一些元素。我已经通过将PushButton提升为“DragButton”并为其创建一个类进行了测试:
from PyQt4 import QtGui, QtCore
class 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 - Drag and Drop 目前,我可以拖动这个按钮,并将其放入另一个具有“acceptDrops”属性设置为true的相同类型的按钮中。但是,我仍然希望限制某些按钮的拖动(可能是通过在UpdateUi方法中设置主文件),因为有些按钮只用于接受拖放。
更新2:现在我正在尝试编写一个类,该类绘制连接这些按钮的线条或“电线”。
我正在尝试在graphicsView中以它们的位置为参考在两个小部件(两个pushbutton)之间画一条线。但是当我尝试时,线条会在错误的位置绘制。我还尝试使用mapToGlobal或mapToParent等函数,但结果仍然不正确。
在同一个类中,我有另一个用鼠标绘制线条的方法,它运行良好。我把它当作参考或示例,但似乎事件位置具有不同的坐标系。好吧,我不知道为什么会发生这种情况。
按钮和graphicsview位于一个小部件内,该小部件也位于窗口内。
以下是这个类,我们正在谈论的方法是from 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 )
如果有更好的实现方式,请告诉我。