PyQt: Nenhum tal ranhura
Pergunta
Eu estou começando a aprender Qt4 e Python, seguindo ao longo de algum tutorial que encontrei na interwebs. Eu tenho os dois seguintes arquivos:
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_())
Quando eu executar este eu recebo os seguintes erros:
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)
Eu li que as faixas horárias PyQt são nada mais do que os métodos que tenho definidos, então o que estou fazendo de errado?
Eu também estou aprendendo Qt4 com Ruby que é onde este se origina de código a partir, eu traduzido lo de Ruby para Python. Na versão do Ruby classe LCDRange é definido como este:
class LCDRange < Qt::Widget
signals 'valueChanged(int)'
slots 'setValue(int)'
def initialize(parent = nil)
...
Então, meu palpite era que eu tenho que declarar alguma forma a existência do slot personalizado?
Solução
Tente isto:
self.connect(lcdRange, QtCore.SIGNAL('valueChanged'), previousRange.setValue)
Qual é a diferença?
A documentação PyQt tem uma seção sobre os sinais / slots no PyQt, eles trabalham um pouco diferente.
SINAL
SIGNAL('valueChanged')
é algo chamado curto circuito de sinal. Eles trabalham apenas para métodos Python-a-Python, mas eles são mais rápidos e mais fáceis de implementar.
SLOT
Se você tem um slot de python, você pode especificá-lo apenas por depósito do método: previousRange.setValue
. Isso funciona para todos os métodos acessíveis por Python.
Se os slots devem ser acessíveis como ranhuras C ++ Qt, como você tentou no seu código, você tem que usar uma sintaxe especial. Você pode encontrar informações sobre pyqtSignature decorador no site do PyQt.
Outras dicas
Você esqueceu de colocar
@Qt.pyqtSlot()
método acima você está usando como slot.
Por exemplo, seu código deve ter esta aparência
@Qt.pyqtSlot('const QPoint&')
def setValue(self,value):
self.slider.setValue(value)
Aqui está uma página bem sobre decorador entalhe PyQt:
Bye
NOTA
O "texto" dentro do sinal deve corresponder ao c ++ documentação da 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 &