简体   繁体   中英

How to override PySide2 widget's method generated by Qt Designer?

I'm trying to learn PySide2 by creating a mimic executable like powerrename tool in powertoys.

After successfully loading the Ui_PowerRenameDialog, which is generated from a .ui file created by Qt Designer.

I encountered an error trying to accomplish a functionality which can let users drag and drop files from Windows Explorer to the QTreeWidget embedded in the .ui file.

Here is my full code:

import sys
from PySide6 import QtWidgets
from PySide6 import QtCore
from ui_powerRename import Ui_PowerRenameDialog

class MyPowerRenameDialog(QtWidgets.QDialog):
    def __init__(self,parent=None):
        super().__init__(parent)

        self.ui = Ui_PowerRenameDialog()
        self.ui.setupUi(self)

        self.modify_ui()
        self.create_connections()


    def modify_ui(self):
        self.ui.previewTreeWidget.setAcceptDrops(True)

        def dragEnterEvent(self,evt):
            if evt.mimeData().hasUrls():
                evt.accept()
            else:
                evt.ignore()

        def dropEvent(self,evt):
            for url in evt.mimeData().urls():
                newItem = QtWidgets.QTreeWidgetItem(url)
                self.addTopLevelItem(newItem)

        self.ui.previewTreeWidget.dragEnterEvent = dragEnterEvent
        self.ui.previewTreeWidget.dropEvent = dropEvent

        items = QtWidgets.QTreeWidgetItemIterator(self.ui.previewTreeWidget)
        for item in items:
            item.value().setFlags(item.value().flags()|QtCore.Qt.ItemIsUserCheckable)
            item.value().setCheckState(0,QtCore.Qt.Checked)

    def create_connections(self):
        self.ui.cancelButton.clicked.connect(self.close)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)

    window = MyPowerRenameDialog()
    window.show()

    sys.exit(app.exec_())

================================================================

Here is what I achieved so far (the red region is the QTreeWidget): The executable snapshot:
可执行快照

As you can see, I tried to overload the dragEnterEvent and dropEvent methods of the QTreeWidget object. The most important part of the overriding code is showed below:

def dragEnterEvent(self,evt):
    if evt.mimeData().hasUrls():
        evt.accept()
    else:
        evt.ignore()
def dropEvent(self,evt):
    for url in evt.mimeData().urls():
        newItem = QtWidgets.QTreeWidgetItem(url)
        self.addTopLevelItem(newItem)

self.ui.previewTreeWidget.dragEnterEvent = dragEnterEvent
self.ui.previewTreeWidget.dropEvent = dropEvent

===============================================================

The problem is when trying to drag and drop any content from explorer to the QTreeWidget instance, I got a TypeError

TypeError: dragEnterEvent() missing 1 required positional argument: 'evt'.

I tried to search for similar questions.One potential solution is to use installEventFilter .But it only leads me to more errors.

I mean the PySide2 document is really a mess, I can't get any useful information from their poorly formatted doc.

There are only few examples in the doc.And most of them are directly copied from the C++ version, not even changed to Python syntax.

Any idea on how to achieve that Functionality?

And is there any suggested way to learn PySide2?

The error comes from the fact that dragEnterEvent and dropEvent are not bound to a class (because they are nested into another function), that means that self is not automatic, this is why when it is called it expects two parameters, self and evt , but the Qt framework only passes evt .

To modify the behevior of Ui_PowerRenameDialog you should create a subclass of Ui_PowerRenameDialog and implement the two event methods in that subclass

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM