【问题标题】:PyQt: No such slotPyQt:没有这样的插槽
【发布时间】:2010-10-09 08:01:50
【问题描述】:

我开始学习 Qt4 和 Python,遵循我在互联网上找到的一些教程。我有以下两个文件:

lcdrange.py:

from PyQt4 import QtGui, QtCore

class LCDRange(QtGui.QWidget):                        
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)

        lcd = QtGui.QLCDNumber(2)

        self.slider = QtGui.QSlider()
        self.slider.setRange(0,99)
        self.slider.setValue(0)

        self.connect(self.slider, QtCore.SIGNAL('valueChanged(int)'),
                     lcd, QtCore.SLOT('display(int)'))
        self.connect(self.slider, QtCore.SIGNAL('valueChanged(int)'),
                     self, QtCore.SIGNAL('valueChanged(int)'))

        layout = QtGui.QVBoxLayout()
        layout.addWidget(lcd)
        layout.addWidget(self.slider)
        self.setLayout(layout)

    def value(self):
        self.slider.value()

    def setValue(self,value):
        self.slider.setValue(value)

main.py:

import sys
from PyQt4 import QtGui, QtCore

from lcdrange import LCDRange

class MyWidget(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)

        quit = QtGui.QPushButton('Quit')
        quit.setFont(QtGui.QFont('Times', 18, QtGui.QFont.Bold))
        self.connect(quit, QtCore.SIGNAL('clicked()'), QtGui.qApp, QtCore.SLOT('quit()'))

        grid = QtGui.QGridLayout()
        previousRange = None

        for row in range(0,3):
            for column in range(0,3):
                lcdRange = LCDRange()

                grid.addWidget(lcdRange, row, column)
                if not previousRange == None:
                    self.connect(lcdRange, QtCore.SIGNAL('valueChanged(int)'),
                                 previousRange, QtCore.SLOT('setValue(int)'))
                previousRange = lcdRange

        layout = QtGui.QVBoxLayout()
        layout.addWidget(quit)
        layout.addLayout(grid)
        self.setLayout(layout)




app = QtGui.QApplication(sys.argv)

widget = MyWidget()
widget.show()


sys.exit(app.exec_())

当我运行它时,我得到以下错误:

Object::connect: No such slot LCDRange::setValue(int)
Object::connect: No such slot LCDRange::setValue(int)
Object::connect: No such slot LCDRange::setValue(int)
Object::connect: No such slot LCDRange::setValue(int)
Object::connect: No such slot LCDRange::setValue(int)
Object::connect: No such slot LCDRange::setValue(int)
Object::connect: No such slot LCDRange::setValue(int)
Object::connect: No such slot LCDRange::setValue(int)

我读过 PyQt 插槽只不过是我定义的方法,那么我做错了什么?

我也在用 Ruby 学习 Qt4,这是这段代码的来源,我将它从 Ruby 翻译成 Python。在 Ruby 版本中,LCDRange 类定义如下:

class LCDRange < Qt::Widget
  signals 'valueChanged(int)'
  slots 'setValue(int)'

  def initialize(parent = nil)
  ...

所以我的猜测是我必须以某种方式声明自定义插槽的存在?

【问题讨论】:

    标签: python ruby qt4 pyqt


    【解决方案1】:

    试试这个:

    self.connect(lcdRange, QtCore.SIGNAL('valueChanged'), previousRange.setValue)
    

    有什么区别?

    The PyQt documentation 在 PyQt 中有一个关于 SIGNALS/SLOTS 的部分,它们的工作方式略有不同。

    信号

    SIGNAL('valueChanged') 称为short-circuit signal。它们仅适用于 Python 到 Python 方法,但它们更快、更容易实现。

    插槽

    如果你有一个 python 插槽,你可以通过提示方法来指定它:previousRange.setValue。这适用于 Python 可访问的所有方法。

    如果您的插槽应该像 C++ Qt 插槽一样可访问,就像您在代码中尝试的那样,您必须使用特殊语法。您可以在 PyQt 网站上找到有关 pyqtSignature decorator 的信息。

    【讨论】:

    • 现在完美运行,谢谢!现在,如果我只能决定我更喜欢哪个,Python 还是 Ruby...
    • 对我来说,Ruby 编程更有趣。但是,有更多的 Python 库,它更快,而且我不相信 QtRuby 和 PyQt 一样先进。也许它会更好。 :)
    • 上述 PyQt 和 pyqtSignature 装饰器文档的链接现在似乎已失效;相反,pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html 的“新型信号和插槽支持”文档似乎与此处相关。
    【解决方案2】:

    注意

    SIGNAL 中的“文本”必须与 c++ API 文档相匹配。

    # This will work - its IDENTICAL to the documentation 
    QtCore.SIGNAL('customContextMenuRequested(const QPoint&)')
    
    # this wont
    QtCore.SIGNAL('customContextMenuRequested(QPoint&)')
    
    # and this wont
    QtCore.SIGNAL('customContextMenuRequested(const QPoint)')
    
    # Spot the bug 
    QtCore.SIGNAL('selectionChanged(const QItemSelection,const QItemSelection&)')
                                                        ^ < missing &
    

    【讨论】:

      【解决方案3】:

      你忘了放

      
      @Qt.pyqtSlot()
      

      上述方法您正在用作插槽。

      例如,您的代码应如下所示

      
      @Qt.pyqtSlot('const QPoint&')
      def setValue(self,value):
              self.slider.setValue(value)
      

      这是一个关于 pyqt 插槽装饰器的好页面:

      click :-)

      再见

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-10-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多