Drag and drop PyQt5
Я пишу приложение, в котором мне необходимо дать возможность пользователю перетаскивать виджеты с одних виджетов/лейаутов, на другие.
Для того чтобы разобраться в том как это делается я написал небольшую тестовую программу.
Когда я перетаскиваю кнопки внутри одного виджета - это работает,
но если я пытаюсь перетащить кнопку с одного виджета на другой, она исчезает.
Подскажите, как реализовать перетаскивание между виджетами?
from PyQt5 import QtCore, QtGui, QtWidgets
class Button(QtWidgets.QPushButton):
def __init__(self):
super().__init__()
def mouseMoveEvent(self, e):
mimeData = QtCore.QMimeData()
drag = QtGui.QDrag(self)
drag.setMimeData(mimeData)
drag.setHotSpot(e.pos() - self.rect().topLeft())
dropAction = drag.exec_(QtCore.Qt.MoveAction)
class New_Frame(QtWidgets.QFrame):
def __init__(self, f):
super().__init__(f)
self.pushButton = Button()
self.pushButton.setParent(self)
self.pushButton.setGeometry(QtCore.QRect(70, 140, 84, 25))
self.pushButton.setObjectName("pushButton")
self.pushButton.setText("PushButton")
def dragEnterEvent(self, e):
e.accept()
def dropEvent(self, e):
position = e.pos()
e.source().setParent(self)
e.source().move(position)
e.setDropAction(QtCore.Qt.MoveAction)
e.accept()
class Ui_Dialog(QtWidgets.QDialog):
def __init__(self):
super(Ui_Dialog, self).__init__()
self.setObjectName("Dialog")
self.resize(1078, 806)
self.setAcceptDrops(True)
# self.frame = QtWidgets.QFrame(self)
self.frame = New_Frame(self)
self.frame.setGeometry(QtCore.QRect(50, 30, 331, 301))
self.frame.setStyleSheet("background-color: rgb(85, 170, 0);")
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.frame.setAcceptDrops(True)
self.pushButton = Button()
self.pushButton.setParent(self)
# self.pushButton.setGeometry(QtCore.QRect(70, 140, 84, 25))
self.pushButton.setObjectName("pushButton")
self.frame_2 = QtWidgets.QFrame(self)
self.frame_2 = New_Frame(self)
self.frame_2.setGeometry(QtCore.QRect(520, 360, 331, 301))
self.frame_2.setStyleSheet("background-color: rgb(255, 85, 127);")
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.frame_2.setAcceptDrops(True)
self.retranslateUi(self)
QtCore.QMetaObject.connectSlotsByName(self)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.pushButton.setText(_translate("Dialog", "PushButton"))
class New_dialog(Ui_Dialog):
def __init__(self):
super().__init__()
def dragEnterEvent(self, e):
e.accept()
def dropEvent(self, e):
position = e.pos()
e.source().setParent(self)
e.source().move(position)
e.setDropAction(QtCore.Qt.MoveAction)
e.accept()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
# Dialog = QtWidgets.QDialog()
# Dialog = QtWidgets.QDialog()
ui = New_dialog()
# ui.setupUi(Dialog)
ui.show()
sys.exit(app.exec_())
Ответы (1 шт):
Автор решения: S. Nick
→ Ссылка
Попробуйте добавить show() в методах dropEvent().
НИКОГДА НЕ ИЗМЕНЯЙТЕ код, сгенерированный Qt Designer, НИКОГДА.
Создайте другой класс, который наследуется от соответствующего виджета, и используйте созданный класс для его заполнения.
from PyQt5 import QtCore, QtGui, QtWidgets
class Button(QtWidgets.QPushButton):
def __init__(self):
super().__init__()
def mouseMoveEvent(self, e):
mimeData = QtCore.QMimeData()
drag = QtGui.QDrag(self)
drag.setMimeData(mimeData)
drag.setHotSpot(e.pos() - self.rect().topLeft())
dropAction = drag.exec_(QtCore.Qt.MoveAction)
class New_Frame(QtWidgets.QFrame):
def __init__(self, new, parent):
super(New_Frame, self).__init__(parent)
self.pushButton = Button()
self.pushButton.setParent(self)
self.pushButton.setGeometry(QtCore.QRect(70, 140, 84, 35))
self.pushButton.setObjectName("pushButton")
self.pushButton.setText(f"PushButton \n{new}")
def dragEnterEvent(self, e):
e.accept()
def dropEvent(self, e):
position = e.pos()
e.source().setParent(self)
e.source().move(position)
# +++
e.source().show() # +++
e.setDropAction(QtCore.Qt.MoveAction)
e.accept()
#class Ui_Dialog(QtWidgets.QDialog):
# def __init__(self):
# super(Ui_Dialog, self).__init__()
class Ui_Dialog(object): # +++
def setupUi(self, Dialog): # +++
self.setObjectName("Dialog")
self.resize(1078, 806)
self.setAcceptDrops(True)
self.frame = New_Frame('frame', self)
self.frame.setGeometry(QtCore.QRect(50, 30, 331, 301))
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.frame.setStyleSheet("#frame {background-color: rgb(85, 170, 0);}")
self.frame.setAcceptDrops(True)
self.pushButton = Button()
self.pushButton.setParent(self)
self.pushButton.setObjectName("pushButton")
# ??? self.frame_2 = QtWidgets.QFrame(self)
self.frame_2 = New_Frame('frame_2', self)
self.frame_2.setGeometry(QtCore.QRect(520, 360, 331, 301))
self.frame_2.setStyleSheet("background-color: rgb(255, 85, 127);")
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.frame_2.setAcceptDrops(True)
self.retranslateUi(self)
QtCore.QMetaObject.connectSlotsByName(self)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.pushButton.setText(_translate("Dialog", "PushButton\nUi_Dialog"))
#class New_dialog(Ui_Dialog):
class NewDialog(QtWidgets.QDialog, Ui_Dialog):
def __init__(self):
super().__init__()
self.setupUi(self)
def dragEnterEvent(self, e):
e.accept()
def dropEvent(self, e):
position = e.pos()
e.source().setParent(self)
e.source().move(position)
# +++
e.source().show() # +++
e.setDropAction(QtCore.Qt.MoveAction)
e.accept()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
ui = NewDialog()
ui.show()
sys.exit(app.exec_())

