Trying to answer to How to Drag QLineEdit form one cell of QGridLayout to other cell in pyqt?
I have gridlayout with four cells (0,0),(0,1),(1,0),(1,1). Every cell is vertical layout with scrollbar. Initially only (0,0) cell contains QLineEdit in it. I want to drag and drop them in any one of the cells. How can I do it?
I wrote this 3 files code :
main.py
:
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from myui_bis import Ui_Form
class MainWidget(QWidget, Ui_Form):
def __init__(self, *args, **kwargs):
super().__init__()
self.setupUi(self)
self.pushButton.clicked.connect(self.printAcceptDrops)
self.show()
def printAcceptDrops(self):
print('printAcceptDrops : ')
print('Mainwidget : ', self.acceptDrops())
print('self.scrollAreaWidgetContents : ', self.scrollAreaWidgetContents.acceptDrops())
print('self.scrollAreaWidgetContents_2 : ', self.scrollAreaWidgetContents_2.acceptDrops())
print('self.scrollAreaWidgetContents_3 : ', self.scrollAreaWidgetContents_3.acceptDrops())
print('self.scrollAreaWidgetContents_4 : ', self.scrollAreaWidgetContents_4.acceptDrops())
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWidget()
sys.exit(app.exec_())
my mywidgets.py
:
from PyQt5.QtWidgets import QLineEdit, QWidget, QScrollArea, QScroller
from PyQt5.QtCore import Qt, QMimeData
from PyQt5.QtGui import QDrag, QPixmap, QCursor
from PyQt5 import QtGui
from PyQt5 import QtCore
from PyQt5 import QtWidgets
class MyLineEdit(QLineEdit):
def dragEnterEvent(self, e):
print('ENTER DRAG EVENT IN ', self.objectName())
e.accept()
def dropEvent(self, e):
widget = e.source()
print('n dropped on widget !!!!!!!!!!!!nn')
if widget == self :
return
if widget.parent().layout().count() == 1:
print('=============== 1 qlineedit')
widget.parent().layout().parent().setAcceptDrops(True)
widget.setParent(None)
self.parent().layout().insertWidget(self.parent().layout().indexOf(self) , widget)
def mouseMoveEvent(self, e):
if e.buttons() == Qt.LeftButton:
drag = QDrag(self)
mime = QMimeData()
drag.setMimeData(mime)
pixmap = QPixmap(self.size())
self.render(pixmap)
drag.setPixmap(pixmap)
drag.exec_(Qt.MoveAction)
class MyWidget(QWidget):
def dragEnterEvent(self, e):
print('ENTER DRAG EVENT IN ', self.objectName())
print('self.layout.count()', self.layout().count())
e.accept()
def dropEvent(self, e):
pos = e.pos()
widget = e.source()
print('pos : ', pos, 'mouse : ', QCursor.pos())
print('event.source : ', widget , 'event.source.parent() :', widget.parent())
print('event.source name: ', widget.objectName())
print('parent : ', self.parent() , self.parent().objectName())
print('self.layput() : ', self.layout())
print('self.objectName() : ', self.objectName())
if widget.parent().layout().count() == 1:
print('=============== 1 WIDGET')
widget.parent().layout().parent().setAcceptDrops(True)
if self.layout().count() == 0 :
widget.setParent(None)
self.layout().addWidget(widget)
self.setAcceptDrops(False)
class MyScrollArea(QScrollArea):
def __init__(self , parent = None):
super(MyScrollArea, self).__init__(parent)
my PyQt5-Designer ui file translated with pyuic5 myui_bis
:
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import Qt, QMimeData
from PyQt5.QtGui import QDrag
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(698, 672)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
Form.setSizePolicy(sizePolicy)
Form.setAcceptDrops(False)
self.gridLayout = QtWidgets.QGridLayout(Form)
self.gridLayout.setObjectName("gridLayout")
self.scrollArea_3 = MyScrollArea(Form)
self.scrollArea_3.setAcceptDrops(True)
self.scrollArea_3.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scrollArea_3.setWidgetResizable(True)
self.scrollArea_3.setObjectName("scrollArea_3")
self.scrollAreaWidgetContents_3 = MyWidget()
self.scrollAreaWidgetContents_3.setGeometry(QtCore.QRect(0, 0, 315, 303))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.scrollAreaWidgetContents_3.sizePolicy().hasHeightForWidth())
self.scrollAreaWidgetContents_3.setSizePolicy(sizePolicy)
self.scrollAreaWidgetContents_3.setAcceptDrops(True)
self.scrollAreaWidgetContents_3.setObjectName("scrollAreaWidgetContents_3")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents_3)
self.verticalLayout_2.setSpacing(30)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.scrollArea_3.setWidget(self.scrollAreaWidgetContents_3)
self.gridLayout.addWidget(self.scrollArea_3, 1, 0, 1, 1)
self.scrollArea_4 = MyScrollArea(Form)
self.scrollArea_4.setAcceptDrops(True)
self.scrollArea_4.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scrollArea_4.setWidgetResizable(True)
self.scrollArea_4.setObjectName("scrollArea_4")
self.scrollAreaWidgetContents_4 = MyWidget()
self.scrollAreaWidgetContents_4.setGeometry(QtCore.QRect(0, 0, 315, 303))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.scrollAreaWidgetContents_4.sizePolicy().hasHeightForWidth())
self.scrollAreaWidgetContents_4.setSizePolicy(sizePolicy)
self.scrollAreaWidgetContents_4.setAcceptDrops(True)
self.scrollAreaWidgetContents_4.setObjectName("scrollAreaWidgetContents_4")
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents_4)
self.verticalLayout_4.setSpacing(30)
self.verticalLayout_4.setObjectName("verticalLayout_4")
self.scrollArea_4.setWidget(self.scrollAreaWidgetContents_4)
self.gridLayout.addWidget(self.scrollArea_4, 1, 1, 1, 1)
self.scrollArea_2 = MyScrollArea(Form)
self.scrollArea_2.setAcceptDrops(True)
self.scrollArea_2.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scrollArea_2.setWidgetResizable(True)
self.scrollArea_2.setObjectName("scrollArea_2")
self.scrollAreaWidgetContents_2 = MyWidget()
self.scrollAreaWidgetContents_2.setGeometry(QtCore.QRect(0, 0, 315, 304))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.scrollAreaWidgetContents_2.sizePolicy().hasHeightForWidth())
self.scrollAreaWidgetContents_2.setSizePolicy(sizePolicy)
self.scrollAreaWidgetContents_2.setAcceptDrops(True)
self.scrollAreaWidgetContents_2.setObjectName("scrollAreaWidgetContents_2")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents_2)
self.verticalLayout_3.setSpacing(30)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2)
self.gridLayout.addWidget(self.scrollArea_2, 0, 1, 1, 1)
self.scrollArea = MyScrollArea(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(1)
sizePolicy.setVerticalStretch(1)
sizePolicy.setHeightForWidth(self.scrollArea.sizePolicy().hasHeightForWidth())
self.scrollArea.setSizePolicy(sizePolicy)
self.scrollArea.setAcceptDrops(True)
self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = MyWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, -304, 315, 897))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.scrollAreaWidgetContents.sizePolicy().hasHeightForWidth())
self.scrollAreaWidgetContents.setSizePolicy(sizePolicy)
self.scrollAreaWidgetContents.setAcceptDrops(False)
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.verticalLayout = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents)
self.verticalLayout.setSpacing(30)
self.verticalLayout.setObjectName("verticalLayout")
self.lineEdit_1 = MyLineEdit(self.scrollAreaWidgetContents)
self.lineEdit_1.setObjectName("lineEdit_1")
self.verticalLayout.addWidget(self.lineEdit_1)
self.lineEdit_2 = MyLineEdit(self.scrollAreaWidgetContents)
self.lineEdit_2.setObjectName("lineEdit_2")
self.verticalLayout.addWidget(self.lineEdit_2)
self.lineEdit_3 = MyLineEdit(self.scrollAreaWidgetContents)
self.lineEdit_3.setObjectName("lineEdit_3")
self.verticalLayout.addWidget(self.lineEdit_3)
self.lineEdit_4 = MyLineEdit(self.scrollAreaWidgetContents)
self.lineEdit_4.setObjectName("lineEdit_4")
self.verticalLayout.addWidget(self.lineEdit_4)
self.lineEdit_5 = MyLineEdit(self.scrollAreaWidgetContents)
self.lineEdit_5.setObjectName("lineEdit_5")
self.verticalLayout.addWidget(self.lineEdit_5)
self.lineEdit_15 = MyLineEdit(self.scrollAreaWidgetContents)
self.lineEdit_15.setObjectName("lineEdit_15")
self.verticalLayout.addWidget(self.lineEdit_15)
self.lineEdit_14 = MyLineEdit(self.scrollAreaWidgetContents)
self.lineEdit_14.setObjectName("lineEdit_14")
self.verticalLayout.addWidget(self.lineEdit_14)
self.lineEdit_13 = MyLineEdit(self.scrollAreaWidgetContents)
self.lineEdit_13.setObjectName("lineEdit_13")
self.verticalLayout.addWidget(self.lineEdit_13)
self.lineEdit_12 = MyLineEdit(self.scrollAreaWidgetContents)
self.lineEdit_12.setObjectName("lineEdit_12")
self.verticalLayout.addWidget(self.lineEdit_12)
self.lineEdit_11 = MyLineEdit(self.scrollAreaWidgetContents)
self.lineEdit_11.setObjectName("lineEdit_11")
self.verticalLayout.addWidget(self.lineEdit_11)
self.lineEdit_10 = MyLineEdit(self.scrollAreaWidgetContents)
self.lineEdit_10.setObjectName("lineEdit_10")
self.verticalLayout.addWidget(self.lineEdit_10)
self.lineEdit_9 = MyLineEdit(self.scrollAreaWidgetContents)
self.lineEdit_9.setObjectName("lineEdit_9")
self.verticalLayout.addWidget(self.lineEdit_9)
self.lineEdit_8 = MyLineEdit(self.scrollAreaWidgetContents)
self.lineEdit_8.setObjectName("lineEdit_8")
self.verticalLayout.addWidget(self.lineEdit_8)
self.lineEdit_7 = MyLineEdit(self.scrollAreaWidgetContents)
self.lineEdit_7.setObjectName("lineEdit_7")
self.verticalLayout.addWidget(self.lineEdit_7)
self.lineEdit_6 = MyLineEdit(self.scrollAreaWidgetContents)
self.lineEdit_6.setObjectName("lineEdit_6")
self.verticalLayout.addWidget(self.lineEdit_6)
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.gridLayout.addWidget(self.scrollArea, 0, 0, 1, 1)
self.pushButton = QtWidgets.QPushButton(Form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(1)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth())
self.pushButton.setSizePolicy(sizePolicy)
self.pushButton.setObjectName("pushButton")
self.gridLayout.addWidget(self.pushButton, 2, 0, 1, 1)
self.gridLayout.setColumnStretch(1, 1)
self.gridLayout.setRowStretch(1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.lineEdit_1.setText(_translate("Form", "1"))
self.lineEdit_2.setText(_translate("Form", "2"))
self.lineEdit_3.setText(_translate("Form", "3"))
self.lineEdit_4.setText(_translate("Form", "4"))
self.lineEdit_5.setText(_translate("Form", "5"))
self.lineEdit_15.setText(_translate("Form", "6"))
self.lineEdit_14.setText(_translate("Form", "7"))
self.lineEdit_13.setText(_translate("Form", "8"))
self.lineEdit_12.setText(_translate("Form", "9"))
self.lineEdit_11.setText(_translate("Form", "10"))
self.lineEdit_10.setText(_translate("Form", "11"))
self.lineEdit_9.setText(_translate("Form", "12"))
self.lineEdit_8.setText(_translate("Form", "13"))
self.lineEdit_7.setText(_translate("Form", "14"))
self.lineEdit_6.setText(_translate("Form", "15"))
self.pushButton.setText(_translate("Form", "Check AcceptDrops"))
from mywidgets import MyLineEdit, MyScrollArea, MyWidget
Now, the QLineEdit
Widgets are added to the scrollAreas layouts when these are empty but then their acceptDrops attribute is set to False and the next QLineEdit
widgets have to be dropped on the already present ones taking their layout-index positions within the layouts. When no widgrts are left in a layout its acceptDrops value is set to True again.
Only big problem now is that I cannot scroll and drag at the same time in any of the four scrollAreas, but that glitch was present in the previous answer too.
I finally realized that in PyQt5 (correct me if I am wrong) ScrollArea
scroll only using the mouse wheel or by dragging the ScrollBar
itself.
So I was wondering if there is a way to accomplish the result of having the dragging scrolling the area at the same time ?
I’ve heard about QScroller
but I am not sure about what it does and tryed to to figure out what event I should filter when the drag is carried out but I wasnt able to find any clue, moreover I should be able to figure out the verical component of the mouse drag to in some way forward the same to the ScrollArea
or ScrollArea.viewport
(I am not even sure I really understand what a viewport is!!)