拖放小部件实现错误-RuntimeWarning:MetaObjectBuilder :: addMethod:为“放置”提供了无效的方法签名

乐山夏尔马

这是我为此创建的自定义小部件:

from PySide2.QtCore import *
from PySide2.QtWidgets import *
from PySide2.QtGui import *
import os

class DragDropWidget(QWidget):
    def __init__(self, parent=None):
        super(DragDropWidget, self).__init__(parent)
        self.setAcceptDrops(True)

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

    def dragMoveEvent(self, event):
        if event.mimeData().hasUrls:
            if len(event.mimeData().urls()) != 1:
                event.ignore()
            else:
                event.setDropAction(Qt.CopyAction)
                event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasUrls:
            event.setDropAction(Qt.CopyAction)
            event.accept()
            if len(event.mimeData().urls()) != 1:
                event.ignore()
            else:
                url = event.mimeData().urls()[
                    0].toLocalFile()
                if os.path.exists(url):
                    self.emit(SIGNAL("dropped"), url)

        else:
            event.ignore()

我可以从dropEvent函数中打印出文件的位置,但是无法使用connect从我的主函数中访问文件。我的主要功能为此包含以下几行:

self.connect(self.ui.DragDropEncode, SIGNAL("dropped"), self.add_file)
def add_file(self, file):
    print(file)

我已经使用以下命令从另一个文件导入了UI:

from Main_UI import Ui_MainWindow

我在此小部件的以下代码:

   self.DragDropEncode = DragDropWidget(self.AddFileEncode)
   self.DragDropEncode.setAcceptDrops(True)

运行主文件时,出现以下错误:

main.py:55: RuntimeWarning: MetaObjectBuilder::addMethod: Invalid method signature provided for "dropped"
  self.connect(self.ui.DragDropEncode, SIGNAL("dropped"), self.add_file)

此外,删除文件绝对没有任何作用。

我仍然不明白为什么会发生此错误。任何帮助将非常感激。谢谢!

这是一个最小的可重现示例:

main.py

# Importing The Required Modules 
from PySide2 import QtCore, QtWidgets, QtGui
from PySide2.QtCore import *
from PySide2.QtWidgets import *
from PySide2.QtGui import *
import sys


# Importing the GUI file
from Problematic import Ui_MainWindow


class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        # Connects to the "DragDrop" Widget defined in the GUI file
        self.connect(self.ui.DragDrop, SIGNAL("dropped"), self.add_file)

        self.show()

    def add_file(self, file):
        # Just some debugging. Not working from this end.
        print("Signal Recieved:", file)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())

有问题的

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'Problematic.ui'
#
# Created by: PyQt5 UI code generator 5.15.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PySide2 import QtCore, QtGui, QtWidgets
from DragDropWidget import DragDropWidget


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setSpacing(0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.Frame = QtWidgets.QFrame(self.centralwidget)
        self.Frame.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(158, 7, 23, 255), stop:1 rgba(255, 130, 20, 255));")
        self.Frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.Frame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.Frame.setObjectName("Frame")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.Frame)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.DragDrop = DragDropWidget(self.Frame)
        self.DragDrop.setAcceptDrops(True)
        self.DragDrop.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0.248473, y1:0.483, x2:1, y2:0, stop:0.208955 rgba(131, 62, 40, 22), stop:1 rgba(163, 13, 23, 0));\n"
"border: 2px dashed rgba(85, 85, 85, 95);")
        self.DragDrop.setObjectName("DragDrop")
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.DragDrop)
        self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_3.setSpacing(0)
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        self.Text = QtWidgets.QLabel(self.DragDrop)
        font = QtGui.QFont()
        font.setFamily("Microsoft Sans Serif")
        font.setPointSize(80)
        font.setItalic(True)
        font.setStyleStrategy(QtGui.QFont.PreferAntialias)
        self.Text.setFont(font)
        self.Text.setAlignment(QtCore.Qt.AlignCenter)
        self.Text.setObjectName("Text")
        self.horizontalLayout_3.addWidget(self.Text)
        self.horizontalLayout_2.addWidget(self.DragDrop)
        self.horizontalLayout.addWidget(self.Frame)
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.Text.setText(_translate("MainWindow", "Drag & Drop\n"
"Files Here"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

DragDropWidget.py

from PySide2.QtCore import *
from PySide2.QtWidgets import *
from PySide2.QtGui import *
import os

class DragDropWidget(QWidget):
    def __init__(self, type, parent=None):
        super(DragDropWidget, self).__init__(parent)
        self.setAcceptDrops(True)

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

    def dragMoveEvent(self, event):
        if event.mimeData().hasUrls:
            if len(event.mimeData().urls()) != 1:
                event.ignore()
            else:
                event.setDropAction(Qt.CopyAction)
                event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasUrls:
            event.setDropAction(Qt.CopyAction)
            event.accept()
            if len(event.mimeData().urls()) != 1:
                event.ignore()
            else:
                url = event.mimeData().urls()[
                    0].toLocalFile()
                if os.path.exists(url):
                    self.emit(SIGNAL("dropped"), url)
                    # Just Some Debugging, Working from this end
                    print("Signal Emitted:", url)

        else:
            event.ignore()
音乐家

SIGNAL()多年来,人们一直认为使用宏已经过时了,新代码必须始终使用“新样式”信号和插槽语法。

另外,SIGNAL语法应始终具有(可能为空)参数类型列表以用于其签名。PyQt曾经支持所谓的“短路信号”,该信号允许将没有适当签名的自定义信号连接到python可调用对象,并可能发出具有任意数量和类型的参数的信号。这可以通过使用不带括号的信号来实现

如前所述,该语法已过时,并且pyside还删除了对这些短路信号的支持,如PySide和PyQt之间的区别所述

由于这是一个过时且过时的功能,而为此付出的努力是不值得的,因此我们决定不实施它。在PySide代码中,您需要使用类似以下内容的代码:

self.emit(SIGNAL ('text_changed_cb(QString)'), text)

就您而言,由于您没有使用参数,因此应如下所示:

self.connect(self.ui.DragDropEncode, SIGNAL("dropped()"), self.add_file)

但是,正如所说的,这是一个过时的,过时的功能(也太冗长,不是很Python语言)。

解决方案是为该类创建信号并直接发出它们:

class DragDropWidget(QWidget):
    dropped = Signal(str)
    # ...

    def dropEvent(self, event):
        # ...
        self.dropped.emit(url)

然后将实例的信号连接到插槽:

self.ui.DragDropEncode.dropped.connect(self.add_file)

请注意,发出信号时必须遵守自变量签名。在上述情况下,基于您的代码,我假设您正在将mimeData的QUrl转换为字符串。如果您需要发出QUrl,则信号必须反映出:

class DragDropWidget(QWidget):
    dropped = Signal(QUrl)

或者,有两种可能性:您可以使用允许发出任何类型的参数(通用 object签名,或使用信号重载。在这种情况下,您可以使用单个信号,该信号能够发出具有各种参数长度和类型的信号。在这种情况下,将默认使用第一个重载,而其他重载必须使用方括号选择:dropped = Signal(object)emit

class DragDropWidget(QWidget):
    dropped = Signal([str], [QUrl])

    # ...

    def dropEvent(self, event):
        # ...
        url = event.mimeData().urls()[0]
        self.dropped.emit(url.toLocalFile())
        self.dropped[QUrl].emit(url)

如果您需要根据信号的签名连接到不同的插槽,这将很有用:

    self.ui.DragDropEncode.dropped.connect(self.function_that_uses_strings)
    self.ui.DragDropEncode.dropped[QUrl].connect(self.function_that_uses_urls)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

Related 相关文章

热门标签

归档