PySide:QMetaObject.connectSlotsByName发出警告“没有匹配的信号......”但仍然有效..?

时间:2013-05-09 11:13:43

标签: python qt pyside

在Qt Designer中,我创建了一个QDialog窗口并使用pysideuic将其编译为基类,该基类包含初始化所有GUI元素的setupUi方法,并且我将其扩展为实现功能,如:

class MyDialog(QtGui.QDialog, ui_file.Ui_main_dialog):
    def __init__(self, parent=None):
        QtGui.QDialog.__init__(self, parent)
        ui_file.Ui_main_dialog.__init__(self)
        self.setupUi(self)

这个setupUi方法调用了QtCore.QObject.connect我在Qt Designer中创建的信号槽连接,我还在GUI中添加了新的插槽。这些插槽在pysideuic生成的基类中不存在,我将它们添加到MyDialog类,例如。

    def on_list_selection_changed(self):
        self.run_btn.setEnabled(len(self.modules_list.selectedIndexes()) > 0)

对于此示例,在Qt Designer中将插槽称为on_list_selection_changed()(带有空参数列表)。

在初始化时,MyDialog.__init__调用Ui_main_dialog.setupUi,最终调用QtCore.QMetaObject.connectSlotsByName(后两个调用当前正在创建的MyDialog实例的self。这会在sys.stderr上发出以下行:

QMetaObject::connectSlotsByName: No matching signal for on_list_selection_changed()

但是,当连接的modules_list.itemSelectionChanged()modules_listQListWidget)时,信号的行为正确并且会调用插槽。

所以这是我的问题:为什么我收到这个警告?鉴于它似乎无关紧要,我能做什么呢?


编辑:由于我在过去5个月内未收到任何答案,我认为我提供了一个完整的示例,以便更轻松地复制问题。

此示例与上述问题的不同之处在于它仅使用QLineEdit实例。这是代码:

import sys
from PySide import QtCore, QtGui

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        self.lineEdit = QtGui.QLineEdit(Dialog)
        self.lineEdit.setObjectName("lineEdit")
        QtCore.QObject.connect(self.lineEdit, QtCore.SIGNAL("textChanged(QString)"), Dialog.on_lineEdit_changed)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

class MainWindow(QtGui.QMainWindow, Ui_Dialog):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self, parent)
        Ui_Dialog.__init__(self)
        Ui_Dialog.setupUi(self, self)
    @QtCore.Slot(unicode) # signal with no arguments
    def on_lineEdit_changed(self, text):
        print 'Changed to', text

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    mw = MainWindow()
    mw.show()
    sys.exit(app.exec_())

请注意,Ui_Dialog类的代码是由Qt Designer的.ui文件中的pysideuic生成的,但我稍微缩短了一点以更好地突出显示问题。

2 个答案:

答案 0 :(得分:4)

我在C ++中遇到同样的问题。 connectSlotsByName是硬编码的,如果找到一个无法自动连接的插槽,即使您不需要自动连接,因为您已经自己明确地完成了该操作。您可以使用qInstallMsgHandler来抑制警告,或者更好地将消息写在某处,但我不认为有任何方法可以告诉connectSlotsByName您特别关心此案例。

答案 1 :(得分:0)

我迟到了,但以防其他人来这里问同样的问题。

PySide 自动连接信号,这就是它对我的工作方式,因为我不想手动连接。

这里我使用的是 python 3.9 和 PySide2,但对于 PySide6 和其他版本的 python 也是一样的。

import sys
import typing

from PySide2.QtCore import QObject, SignalInstance, Signal, Slot
from PySide2.QtWidgets import QMainWindow, QApplication

from .ui_mainwindow import Ui_MainWindow  # Don't forget to add your import


class MyQObject(QObject):
    mySignal: SignalInstance = Signal()
    otherSignal: SignalInstance = Signal(str)

    def __init__(self, parent: typing.Optional[QObject] = None) -> None:
        super().__init__(parent)


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        # Instantiate before self.setupUI
        self.myQObject = MyQObject(self)
        self.myQObject.setObjectName("syncProduct")  # do not forget this

        # Load UI from designer & init
        self.setupUi(self)

    @Slot()
    def on_myQObject_mySignal(self):
        print("Handle mySignal")

    @Slot(str)
    def on_myQObject_otherSignal(self, text: str):
        print(f"Handle otherSignal {text}")


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