类Form

第一个坑,类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通过信号和槽的关联方式:




需要特别注意的是,在运行程序的时候,在命令行下边,要用完整的 python signals.py 参数  运行,单独运行signals.py,参数无法接收。目前我也没找到好的解决办法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值