pyqt5按钮拖拽,实现拖拽新增和拖拽移动
按钮默认不能拖动,需要重新按钮类,我们的需求是按钮拖动复制和单纯的拖动,所以需要重写两个类
按钮拖动复制
class MyPushButton(QPushButton):
def __init__(self, parent=None, text=''):
super(MyPushButton, self).__init__(parent)
self.text = text
self.setText(text)
def mouseMoveEvent(self, e):
if e.buttons() != Qt.LeftButton:
return
mimeData = QMimeData()
mimeData.setText('add,' + self.text)
drag = QDrag(self)
drag.setMimeData(mimeData)
drag.exec_(Qt.MoveAction)
self.setAcceptDrops(False)
QMimeData类可以设置很多数据,我们只需要使用setText即可,在我们重写的鼠标移动事件中,鼠标移动的时候将携带QMimeData对象。
按钮拖动移动
class MyPushButton2(QPushButton):
def __init__(self, parent=None, text=''):
super(MyPushButton2, self).__init__(parent)
self.text = text
self.setText(text)
def mouseMoveEvent(self, e):
if e.buttons() != Qt.LeftButton:
return
mimeData = QMimeData()
mimeData.setText('move,' + self.text)
drag = QDrag(self)
drag.setMimeData(mimeData)
drag.setHotSpot(e.pos() - self.rect().topLeft())
drag.exec_(Qt.MoveAction)
self.setAcceptDrops(False)
按钮2只是传递的字符信息不同了,这样可以方便我们进行后续处理
按钮可以拖动了(实际上是鼠标携带按钮信息),不代表我们已经可以放置按钮,QGroupBox默认不接受放置,所以我们又需要重新一个类
class MyGroupBox(QGroupBox):
AddSignal = pyqtSignal(list)
MoveSignal = pyqtSignal(list)
def __init__(self, parent=None):
super(MyGroupBox, self).__init__(parent)
self.setAcceptDrops(True)
def dragEnterEvent(self, e):
# print(e)
if e.mimeData().hasText():
e.accept()
else:
e.ignore()
def dropEvent(self, e):
data = e.mimeData().text().split(',')
# print((e.pos().x(), e.pos().y()))
if data[0] == 'add':
self.AddSignal.emit([data[1], e.pos()])
elif data[0] == 'move':
self.MoveSignal.emit([data[1], e.pos()])
这次我们重写了两个方法,dragEnterEvent表示拖动移入事件,dropEvent表示放置事件,setAcceptDrops用来设置我们的类是否接收放置事件,默认是False。我们通过判断字符信息将按钮数据通过不同的信号发送给主窗口,主窗口再通过绑定不同函数执行相应的操作。
完整代码:
import sys
from PyQt5.QtCore import pyqtSignal, QMimeData, Qt
from PyQt5.QtGui import QDrag
from PyQt5.QtWidgets import QApplication, QGridLayout, QGroupBox, QWidget, QPushButton
class MyPushButton(QPushButton):
def __init__(self, parent=None, text=''):
super(MyPushButton, self).__init__(parent)
self.text = text
self.setText(text)
def mouseMoveEvent(self, e):
if e.buttons() != Qt.LeftButton:
return
mimeData = QMimeData()
mimeData.setText('add,' + self.text)
drag = QDrag(self)
drag.setMimeData(mimeData)
drag.exec_(Qt.MoveAction)
self.setAcceptDrops(False)
class MyPushButton2(QPushButton):
def __init__(self, parent=None, text=''):
super(MyPushButton2, self).__init__(parent)
self.text = text
self.setText(text)
def mouseMoveEvent(self, e):
if e.buttons() != Qt.LeftButton:
return
mimeData = QMimeData()
mimeData.setText('move,' + self.text)
drag = QDrag(self)
drag.setMimeData(mimeData)
drag.setHotSpot(e.pos() - self.rect().topLeft())
drag.exec_(Qt.MoveAction)
self.setAcceptDrops(False)
class MyGroupBox(QGroupBox):
AddSignal = pyqtSignal(list)
MoveSignal = pyqtSignal(list)
def __init__(self, parent=None):
super(MyGroupBox, self).__init__(parent)
self.setAcceptDrops(True)
def dragEnterEvent(self, e):
# print(e)
if e.mimeData().hasText():
e.accept()
else:
e.ignore()
def dropEvent(self, e):
data = e.mimeData().text().split(',')
# print((e.pos().x(), e.pos().y()))
if data[0] == 'add':
self.AddSignal.emit([data[1], e.pos()])
elif data[0] == 'move':
self.MoveSignal.emit([data[1], e.pos()])
class DragDemoView(QWidget):
def __init__(self):
super(DragDemoView, self).__init__()
self.setUI()
self.show()
def setUI(self):
self.setWindowTitle("DragDemoView")
self.resize(QApplication.desktop().availableGeometry().width() - 400,
QApplication.desktop().availableGeometry().height() - 200)
self.drawBox = MyGroupBox(self)
self.drawBox.AddSignal.connect(self.add_button)
self.drawBox.MoveSignal.connect(self.move_button)
self.toolBox = QGroupBox(self)
self.button1 = MyPushButton(self.toolBox, 'test')
self.buttonDict = {}
self.layout = QGridLayout(self)
self.layout.addWidget(self.toolBox, 0, 0, 1, 1)
self.layout.addWidget(self.drawBox, 0, 1, 1, 1)
def add_button(self, data):
n = 0
buttonName = data[0] + str(n)
while buttonName in self.buttonDict:
n += 1
buttonName = data[0] + str(n)
button = MyPushButton2(self.drawBox, buttonName)
self.buttonDict[buttonName] = button
button.move(data[1])
button.show()
def move_button(self, data):
button = self.buttonDict[data[0]]
button.move(data[1])
button.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
main = DragDemoView()
app.exit(app.exec_())
主窗口决定了按钮的复制和移动,实际上就是通过按钮所传递的信息进行的操作,所有按钮信息必须唯一(上面的程序是通过判断按钮上的文字)。
如有疑问,可以评论联系我,谢谢。