我开始学习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)
...
所以我的猜测是我必须以某种方式声明自定义插槽的存在?
答案 0 :(得分:7)
试试这个:
self.connect(lcdRange, QtCore.SIGNAL('valueChanged'), previousRange.setValue)
The PyQt documentation在PyQt中有一个关于SIGNALS / SLOTS的部分,它们的工作方式略有不同。
SIGNAL('valueChanged')
称为short-circuit signal。它们仅适用于Python-to-Python方法,但它们更快更容易实现。
如果你有一个python插槽,你可以通过小费方法指定它:previousRange.setValue
。这适用于Python可访问的所有方法。
如果您的插槽应该像C ++ Qt插槽一样可访问,就像在代码中尝试的那样,您必须使用特殊语法。您可以在PyQt网站上找到有关pyqtSignature decorator的信息。
答案 1 :(得分:1)
你忘记了
@Qt.pyqtSlot()
以上用作插槽的方法。
例如,您的代码应如下所示
@Qt.pyqtSlot('const QPoint&')
def setValue(self,value):
self.slider.setValue(value)
这是关于pyqt slot decorator的一个很好的页面:
再见
答案 2 :(得分:0)
请注意
SIGNAL中的“text”必须与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 &