专栏名称: vinwzh
不知不觉,我们在得到的同时也在失去着什么。
目录
相关文章推荐
沈阳网  ·  突然暴涨!超600%! ·  昨天  
璞缇客精品酒店  ·  悦榕集团首家!不是瑞士!湿地公园里的奢华新地 ... ·  4 天前  
贵州省文化和旅游厅  ·  省内唯一!贵州省坝陵河桥梁博物馆入选全国第一 ... ·  4 天前  
贵州省文化和旅游厅  ·  省内唯一!贵州省坝陵河桥梁博物馆入选全国第一 ... ·  4 天前  
51好读  ›  专栏  ›  vinwzh

PySide2学习记录(七):稍微复杂的信号和槽

vinwzh  · 简书  ·  · 2018-11-25 10:00

正文

Python2.7
PySide2 Version: 5.11.2
官方文档:http://doc.qt.io/qtforpython/index.html

import sys
from PySide2 import QtCore, QtGui, QtWidgets


class LCDRange(QtWidgets.QWidget):
    valueChanged = QtCore.Signal(int)
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)

        lcd = QtWidgets.QLCDNumber(2)

        self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        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 = QtWidgets.QVBoxLayout()
        layout.addWidget(lcd)
        layout.addWidget(self.slider)
        self.setLayout(layout)

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

    @QtCore.Slot(int)
    def setValue(self, value):
        self.slider.setValue(value)


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

        quit = QtWidgets.QPushButton("Quit")
        quit.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold))

        self.connect(quit, QtCore.SIGNAL("clicked()"),
                     QtWidgets.qApp, QtCore.SLOT("quit()"))

        grid = QtWidgets.QGridLayout()
        previousRange = None

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

        for row in range(3):
            for column in range(3):
                lcdRange = LCDRange()
                grid.addWidget(lcdRange, row, column)
                if previousRange:
                    self.connect(lcdRange, QtCore.SIGNAL("valueChanged(int)"),
                                 previousRange.setValue)
                previousRange = lcdRange

app = QtWidgets.QApplication(sys.argv)
widget = MyWidget()
widget.show()
sys.exit(app.exec_())

运行效果:

图1

这次在上次的基础上添加了一些信号和槽,上次的每个单独滑动,不会相互影响,而这次这个后面的widget会影响前面所有的widget,接下来看看是如何实现的。

class LCDRange(QtWidgets.QWidget):
    valueChanged = QtCore.Signal(int)

    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)

        lcd = QtWidgets.QLCDNumber(2)

        self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        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 = QtWidgets.QVBoxLayout()
        layout.addWidget(lcd)
        layout.addWidget(self.slider)
        self.setLayout(layout)

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

    @QtCore.Slot(int)
    def setValue(self, value):
        self.slider.setValue(value)

valueChanged = QtCore.Signal(int)
为LCDRange添加一个信号,名字叫valueChanged(这个名字自己随便起)。有的人可能有点疑惑,因为LCDRange里面的slider已经有了valueChanged信号,为什么还要给LCDRange再新添加一个valueChanged信号呢,注意现在要把LCDRange视为一个整体,而slider只是LCDRange里面的一个控件而已,其实我们自定义的LCDRange目前就只有一个valueChanged信号和2个控件,还有一个槽(后面介绍),而当slider发射这个信号时,仅仅代表这个slider,而由于我们要把LCDRange当成一个整体,所以需要给LCDRange这个类里面添加一个能够代表LCDRange的信号。

self.connect(self.slider, QtCore.SIGNAL("valueChanged(int)"), self, QtCore.SIGNAL("valueChanged(int)"))
在这里可以看到,self代表LCDRange本身,valueChanged(int)表示这个对象的信号,这里和之前的也不一样,之前是信号对应槽,而这里是信号对应着信号,相当于slider发送的这个信号,LCDRange收到后也会发送一个信号,而这里的信号是我们定义的valueChanged(int)信号,也可以定义我们所需要的。

@QtCore.Slot(int)
    def setValue(self, value):
        self.slider.setValue(value)

这是自定义的槽,叫setValue。用@QtCore.Slot(int)来进行修饰,int表示传了一个int类型的参数,同样这个槽属于LCDRange类。

接下来是MyWidget类中的这条语句
self.connect(lcdRange, QtCore.SIGNAL("valueChanged(int)"), previousRange.setValue)
这条语句作用是把我们定义的LCDRange的对象进行信号和槽连接。
这时connect只有三个参数,第一个是发送这个信号的对象,第二个是要发送的信号,第三个是接收信号的槽。而接收的槽是上一个对象的槽,同时这个信号和槽都属于LCDRange类。