【问题标题】:Correct way to convert old SIGNAL and SLOT to new style?将旧信号和插槽转换为新样式的正确方法?
【发布时间】:2018-04-03 06:21:36
【问题描述】:

我目前正在尝试将旧的 python 程序从 Python 2 转换为 Python 3,并从 PyQt4 更新为 PyQt5。该应用程序使用 PyQt5 不支持的旧式信号和插槽。我已经弄清楚了大部分需要做的事情,但下面有几行我似乎无法工作:

self.emit(SIGNAL('currentChanged'), row, col)
self.emit(SIGNAL("activated(const QString &)"), self.currentText())
self.connect(self,SIGNAL("currentChanged(const QString&)"), self.currentChanged)

前两行,我不知道从哪里开始,因为它们似乎没有附加任何东西。最后一个例子我不太清楚该怎么处理 (const QString &)。

我不完全确定如何处理这些问题,而且我仍在学习 python,但我们将不胜感激。

编辑:文档似乎并没有真正深入探讨这些案例,至少以我理解的方式。

【问题讨论】:

    标签: python syntax pyqt4 pyqt5 signals-slots


    【解决方案1】:

    这个问题的确切答案将取决于self 是什么类型的对象。如果它是一个已经定义了这些信号的 Qt 类,那么新式语法将是这样的:

    self.currentChanged[int, int].emit(row, col)
    self.activated[str].emit(self.currentText())
    self.currentChanged[str].connect(self.handleCurrentChanged)
    

    但是,如果其中任何一个 不是 预定义的,则您需要为它们定义自定义信号,如下所示:

    class MyClass(QWidget):
        # this defines two overloads for currentChanged
        currentChanged = QtCore.pyqtSignal([int, int], [str])
        activated = QtCore.pyqtSignal(str)
    
        def __init__(self, parent=None):
            super(MyClass, self).__init__(parent)
            self.currentChanged[str].connect(self.handleCurrentChanged)   
    
        def handleCurrentChanged(self, text):
            print(text)
    

    旧式语法允许动态发出自定义信号(即无需先定义它们),但这已不再可能。使用新式语法,必须始终明确定义自定义信号。

    请注意,如果只为信号定义了一个重载,则可以省略选择器:

        self.activated.emit(self.currentText())
    

    有关更多信息,请参阅 PyQt 文档中的这些文章:

    编辑

    对于您的实际代码,您需要对currentChanged 信号进行以下更改:

    1. Multibar.py 中(大约第 30 行):

      这定义了一个自定义信号(因为QWidget 没有它):

      class MultiTabBar(QWidget):
          # add the following line
          currentChanged = pyqtSignal(int, int)
      
    2. Multibar.py 中(大约第 133 行):

      这会发出 (1) 中定义的自定义信号:

      # self.emit(SIGNAL('currentChanged'), row, col)
      self.currentChanged.emit(row, col)
      
    3. ScWindow.py 中(第 478 行附近):

      这将连接(1)中定义的信号:

          # self.connect(self.PieceTab,SIGNAL("currentChanged"),self.pieceTabChanged)
          self.PieceTab.currentChanged.connect(self.pieceTabChanged)
      
    4. ItemList.py 中(大约第 73 行):

      QFileDialogalready defines this signal,它只有一个重载。但是必须更改槽的名称,因为它隐藏了内置信号名称(这已成为新式语法中的属性)。所以连接应该是这样的:

          # self.connect(self,SIGNAL("currentChanged(const QString&)"),self.currentChanged)
          self.currentChanged.connect(self.onCurrentChanged)
      
    5. ItemList.py 中(大约第 78 行):

      这将重命名 (4) 中建立的连接的插槽:

          # def currentChanged(self, file):
          def onCurrentChanged(self, file):
      

    【讨论】:

    • 我最初尝试使用 self.currentChanged[int, int].emit(row, col) ,但一直收到一个错误,即对象(QWidget)没有属性 'currentChanged',但是旧行self.emit(SIGNAL('currentChanged'), row, col) 工作得很好。我的理解是 currentChanged 是一个预定义的信号,这就是为什么我没有看到为 currentChanged 定义的重载,但如果旧代码是,我仍然无法弄清楚为什么它不起作用。
    • @AaronTomason。我的回答已经涵盖了所有这些。如果类尚未定义自定义信号,则必须定义它。 self 到底是一个什么样的对象?它的类别是什么?旧式语法允许您动态地发出信号(无需先定义它们),但对于新式语法则不行。如果它们不存在,则必须定义。
    • 对象是一个QWidget。在阅读了更多关于 QItemSelection 的内容后,currentChanged 被列为一个信号,并且由于旧代码按预期工作,我认为定义 currentChanged 不是必需的,毕竟旧代码都在工作。我相信这是我迷路的地方。我查看了 QWidget 文档,但没有看到 currentChanged 列出,它在 QTabWidget 下列出,但我想这意味着旧样式仍然无法工作。
    • @AaronTomason。正如我在回答和之前的评论中所说:旧式语法允许发出未定义的信号,但新式不允许。因此,您必须定义currentChanged 信号,就像我在回答中所做的那样。请您试一试,并确认它有效吗?
    • 我很抱歉,我一定忽略了你最初回答的那部分,但现在这完全有道理。我会做出一些改变,并就此与您联系。谢谢!
    猜你喜欢
    • 2018-04-02
    • 1970-01-01
    • 2020-06-29
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 2013-09-27
    • 2016-05-13
    • 2016-09-06
    相关资源
    最近更新 更多