wps2000 |
2016-10-13 21:27 |
第一个坑,类Form。里面涉及到需要修改的,还是connet方法,原来的是这样: ========================================= self.connect(dial, SIGNAL("valueChanged(int)"), spinbox.setValue) self.connect(spinbox, SIGNAL("valueChanged(int)"), dial.setValue) ========================================= 在PyQt5,必须改成: ========================================= dial.valueChanged.connect(spinbox.setValue) spinbox.valueChanged.connect(dial.setValue) ========================================= 也就是说,建立各类的连接必须由该类的connect方法去实现。这样语法更为简洁。 第二个坑,类Form2。在“connet”这一部份,作者使用了QT槽,据说用SLOT()语法可能会更高效一些(中文版书P96): ========================================= self.connect(dial, SIGNAL("valueChanged(int)"), spinbox, SLOT("setValue(int)")) self.connect(spinbox, SIGNAL("valueChanged(int)"), dial, SLOT("setValue(int)")) ========================================= 查了一下官网,这种方法已经不支持了。 SIGNAL和SLOT已经作为装饰器使用了。总之,Form2还是得改成上面Form的样子: ========================================= dial.valueChanged.connect(spinbox.setValue) spinbox.valueChanged.connect(dial.setValue) ========================================= 第三个坑,类ZeroSpinBox和Form3。这两个类是相关联的。也是最大的一个坑。先上原来的代码: ======================================================================= class ZeroSpinBox(QSpinBox): zeros = 0 def __init__(self, parent=None): super(ZeroSpinBox, self).__init__(parent) self.connect(self, SIGNAL("valueChanged(int)"), self.checkzero) def checkzero(self): if self.value() == 0: self.zeros += 1 self.emit(SIGNAL("atzero"), self.zeros) class Form3(QDialog): def __init__(self, parent=None): super(Form3, self).__init__(parent) dial = QDial() dial.setNotchesVisible(True) zerospinbox = ZeroSpinBox() layout = QHBoxLayout() layout.addWidget(dial) layout.addWidget(zerospinbox) self.setLayout(layout) self.connect(dial, SIGNAL("valueChanged(int)"), zerospinbox, SLOT("setValue(int)")) self.connect(zerospinbox, SIGNAL("valueChanged(int)"), dial, SLOT("setValue(int)")) self.connect(zerospinbox, SIGNAL("atzero"), self.announce) self.setWindowTitle("Signals and Slots") def announce(self, zeros): print "ZeroSpinBox has been at zero %d times" % zeros ======================================================================= 在类ZeroSpinBox里面,有一个很让人费解的东西,就是SIGNAL("atzero"),简直就是凭空出来的,原书上说“它会发射自定义的atzero”信号,但在PYQT5中,这种自定义的信号必须先用 pyqtSignal初始化: atzero = pyqtSignal(int) 然后才能发射出去。 self.atzero.emit(self.zeros),对比一下原来的方法: self.emit(SIGNAL("atzero"), self.zeros),和connect的使用方法很相似。 另外,在类Form3中的这几个语句: self.connect(dial, SIGNAL("valueChanged(int)"), zerospinbox, SLOT("setValue(int)")) self.connect(zerospinbox, SIGNAL("valueChanged(int)"), dial, SLOT("setValue(int)")) self.connect(zerospinbox, SIGNAL("atzero"), self.announce) 要改成: dial.valueChanged.connect(zerospinbox.setValue) zerospinbox.valueChanged.connect(dial.setValue) zerospinbox.atzero.connect(self.announce) 这下简洁多了。zerospinbox.atzero.connect(self.announce)这一句,实际上是将atzero与announce方法相连接。只要拔号盘归零一次,就将归零的次数显示出来。announce为作一个“槽”,是要加上装饰器的,所以才有了下面的改动: @pyqtSlot(int) def announce(self, zeros): print("ZeroSpinBox has been at zero %d times" % zeros) 第四个,有了前面的坑,这都不算坑了,类From4: self.connect(lineedit, SIGNAL("textChanged(QString)"), self.consoleEcho) 改成 lineedit.textChanged.connect(self.consoleEcho) 将consoleEcho方法,加上装饰器,作为槽使用: @pyqtSlot(str) def consoleEcho(self, text): print(text) 原来的unicode(text),要将unicode去掉,因为phtyon3.x默认是unicode 第五个坑,类TaxRate和外部函数rateChanged ================================================ class TaxRate(QObject): def __init__(self): super(TaxRate, self).__init__() self.__rate = 17.5 def rate(self): return self.__rate def setRate(self, rate): if rate != self.__rate: self.__rate = rate self.emit(SIGNAL("rateChanged"), self.__rate) def rateChanged(value): print "TaxRate changed to %.2f%%" % value ================================================ 这里迷惑人的是,SIGNAL("rateChanged")里的rateChanged,不是那个外部函数, rateChanged(value),而是和前面的atzero一样,是一个信号。所以,事先也要是必须要初始化的: rateChanged = pyqtSignal(float) 然后,setRate方法里的emit方法,要改成:self.rateChanged.emit(self.__rate)。用rateChanged这个信号将self.__rate发射出去,发射到 rateChanged(value)这个函数里。因此,最后的代码: ================================================ vat = TaxRate() vat.connect(vat, SIGNAL("rateChanged"), rateChanged) vat.setRate(17.5) # No change will occur (new rate is the same) vat.setRate(8.5) # A change will occur (new rate is different) ================================================ vat对象的connet方法,要改成:vat.rateChanged.connect(rateChanged),vat后面跟的rateChanged是信号,connect后面跟的rateChanged,是那个外部函数 rateChanged(value)。 第六个坑: 书中的源代码文件是signals.pyw,必须另存为signals.py,这个程序在命令提示符中显示出输出的内容。为什么会这样?因为pyw文件是静默模式,所有向原有的 stdout 和 stderr 的输出都无效,所有从原有的 stdin 的读取都只会得到 EOF 最后,上个图,理解一下ZeroSpinBox和 Form3通过信号和槽的关联方式: [attachment=15883] 需要特别注意的是,在运行程序的时候,在命令行下边,要用完整的 python signals.py 参数 运行,单独运行signals.py,参数无法接收。目前我也没找到好的解决办法。
|
|