《快速掌握PyQt5》第二章 信号与槽——裁判鸣枪与选手开跑

第二章  信号与槽——裁判鸣枪与选手开跑

2.1 通过按钮来改变文本(一个信号连接一个槽)

2.2 多个信号连接同一个槽

2.3 一个信号与另外一个信号连接

2. 4 一个信号连接多个槽

2.5 自定义信号

2.6 小结


 《快速掌握PyQt5》专栏已整理成书出版,书名为《PyQt编程快速上手》,详情请见该链接。感谢大家一直以来的支持!祝大家PyQt用得越来越顺!

不用多说,信号(signal)与槽(slot)机制很重要。在这里我把信号视作裁判鸣枪,而用于行动的槽函数则视作选手开跑,当裁判鸣枪后(即信号发出),选手就开始往前跑(槽函数启动)。PyQt5中各个对象间或各个对象自身就是通过信号与槽机制来相互通信的,下面来看一个例子。

2.1 通过按钮来改变文本(一个信号连接一个槽)

很多程序上是有“开始”按钮的,按下去后按钮上的文本就变成了“停止”。下面就是一个示例(之后的代码都会用类来呈现):

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton


class Demo(QWidget):                                            # 1
    def __init__(self):
        super(Demo, self).__init__()
        self.button = QPushButton('Start', self)                # 2
        self.button.clicked.connect(self.change_text)           # 3

    def change_text(self):
        print('change text')
        self.button.setText('Stop')                             # 4
        self.button.clicked.disconnect(self.change_text)        # 5


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()                                               # 6
    demo.show()                                                 # 7
    sys.exit(app.exec_())

1. 该类继承QWidget,可以将QWidget看作是一种毛坯房,还没有装修,而我们往其中放入QPushButton、QLabel等控件就相当于在装修这间毛坯房。类似的毛坯房还有QMainWindow和QDialog,之后章节再讲述;

2. 实例化一个QPushButton,因为继承于QWidget,所以self不能忘了(相当于告诉程序这个QPushButton是放在QWidget这个房子中的);

3. 连接信号与槽函数。self.button就是一个控件,clicked(按钮被点击)是该控件的一个信号,connect()即连接,self.change_text即下方定义的函数(我们称之为槽函数)。所以通用的公式可以是:widget.signal.connect(slot);

4. 将按钮文本从‘Start’改成‘Stop’;

5. 信号和槽解绑,解绑后再按按钮你会发现控制台不会再输出‘change text’,如果把这行解绑的代码注释掉,你会发现每按一次按钮,控制台都会输出一次‘change text’;

6. 实例化Demo类;

7. 使demo可见,其中的控件自然都可见(除非某控件刚开始设定隐藏)

现在用鸣枪和开跑来分析下上面这个例子:按钮控件是裁判,他鸣枪发出信号(clicked),change_text()槽函数运行就是选手开跑。

运行以上代码,窗口显示如下:

点击之后文本则改变:

2.2 多个信号连接同一个槽

2.1这个示例是用一个信号连接一个槽,现在来看下多个信号连接同一个槽。

QPushButton还有两个信号是pressed和released,这两个信号解释如下:

  • pressed: 当鼠标在button上并点击左键的时候,触发信号 。
  • released: 当鼠标左键被释放的时候触发信号。

所以其实pressed和released两个连起来就是一个完整的clicked。

下面用这两个信号来解释如何将多个信号连接到同一个槽:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton


class Demo(QWidget):
    def __init__(self):
        super(Demo, self).__init__()
        self.button = QPushButton('Start', self)
        self.button.pressed.connect(self.change_text)     # 1
        self.button.released.connect(self.change_text)    # 2

    def change_text(self):
        if self.button.text() == 'Start':                 # 3
            self.button.setText('Stop')
        else:
            self.button.setText('Start')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

1-2. 将pressed和released信号连接搭配change_text()槽函数上;

3. 若当前按钮文本为‘Start’,则将文本改为‘Stop’;若为‘Stop’,则改为‘Start’。

所以当鼠标点击按钮不放时,发出pressed信号,调用槽函数,将‘Start’文本改为‘Stop’;当鼠标放开后释放released信号,再次调用槽函数,将文本改回‘Start’。

运行截图如下,点击不放时:

放开后:

2.3 一个信号与另外一个信号连接

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton


class Demo(QWidget):
    def __init__(self):
        super(Demo, self).__init__()
        self.button = QPushButton('Start', self)
        self.button.pressed.connect(self.button.released)  # 1
        self.button.released.connect(self.change_text)     # 2

    def change_text(self):
        if self.button.text() == 'Start':
            self.button.setText('Stop')
        else:
            self.button.setText('Start')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

1-2. 将pressed信号和released信号连接起来,而released信号则与槽函数连接。这样当点击不放时,pressed信号发出,released信号也会发出,从而启动槽函数。释放鼠标则发出released信号,再次启动槽函数。所以程序运行效果跟2.2小节其实是一样的。

2. 4 一个信号连接多个槽

信号都为clicked,然后再多定义几个槽函数:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton


class Demo(QWidget):
    def __init__(self):
        super(Demo, self).__init__()
        self.resize(300, 300)                                   # 1
        self.setWindowTitle('demo')                             # 2
        self.button = QPushButton('Start', self)
        self.button.clicked.connect(self.change_text)
        self.button.clicked.connect(self.change_window_size)    # 3
        self.button.clicked.connect(self.change_window_title)   # 4

    def change_text(self):
        print('change text')
        self.button.setText('Stop')
        self.button.clicked.disconnect(self.change_text)

    def change_window_size(self):                               # 5
        print('change window size')
        self.resize(500, 500)
        self.button.clicked.disconnect(self.change_window_size)

    def change_window_title(self):                              # 6
        print('change window title')
        self.setWindowTitle('window title changed')
        self.button.clicked.disconnect(self.change_window_title)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()                                               
    demo.show()                                                 
    sys.exit(app.exec_())

1. 首先在初始化函数中将窗口大小设置为宽300,长300;

2. 其次将窗口名称设置为‘demo’;

3-4. 信号和槽连接,可以看到信号还是clicked,而槽函数多了两个; 

5. 修改窗口大小的槽函数;

6. 修改窗口名称的槽函数;

现在运行点击按钮后,按钮文本会由‘Start’变为‘Stop’,窗口大小从(300, 300)变为(500, 500),窗口标题由‘demo’变为‘window title changed’

以下是运行截图:

点击后则变成:

2.5 自定义信号

注意这里将QPushButton换成了QLabel来讲解:

import sys
from PyQt5.QtCore import pyqtSignal                             # 1
from PyQt5.QtWidgets import QApplication, QWidget, QLabel


class Demo(QWidget):
    my_signal = pyqtSignal()                                    # 2

    def __init__(self):
        super(Demo, self).__init__()
        self.label = QLabel('Hello World', self)
        self.my_signal.connect(self.change_text)                # 3

    def change_text(self):
        if self.label.text() == 'Hello World':
            self.label.setText('Hello PyQt5')
        else:
            self.label.setText('Hello World')

    def mousePressEvent(self, QMouseEvent):                     # 4
        self.my_signal.emit()                                   


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

1. 需要先导入pyqtSignal;

2. 实例化一个自定义的信号;

3. 将自定义的信号连接到自定义的槽函数上;

4. mousePressEvent()方法是许多控件自带的,这里来自于QWidget。该方法用来监测鼠标是否有按下。现在鼠标若被按下,则会发出自定义的信号。

运行截图如下:

当在窗体空白处按下鼠标,则文本发生变化:

关于自定义信号的详细用法,请大家阅读《PyQt5高级编程实战》自定义信号详解

2.6 小结

1. 可以将信号和槽视作裁片鸣枪与选手开跑,信号发出,则相应连接的槽函数启动;

2. 单个信号可以连接单个槽;单个信号可以连接多个槽;多个信号可以连接单个槽;信号可以与信号连接;也可以自定义信号;

3. mousePressEvent()方法是许多控件自带的方法,用来监测鼠标是否被按下。
 

欢迎关注我的微信公众号,发现更多有趣内容:

  • 31
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
PyQt5中的按钮可以使用QPushButton类创建。您可以使用QPushButton的clicked信号连接到一个,该将在按下按钮时被调用。 以下是一个简单的示例,演示如何在PyQt5中创建按钮组以及如何连接按钮的clicked信号: ```python import sys from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout class MyWidget(QWidget): def __init__(self): super().__init__() # 创建三个按钮 self.button1 = QPushButton("Button 1") self.button2 = QPushButton("Button 2") self.button3 = QPushButton("Button 3") # 将按钮添加到垂直布局中 layout = QVBoxLayout() layout.addWidget(self.button1) layout.addWidget(self.button2) layout.addWidget(self.button3) self.setLayout(layout) # 连接按钮的clicked信号 self.button1.clicked.connect(self.buttonClicked) self.button2.clicked.connect(self.buttonClicked) self.button3.clicked.connect(self.buttonClicked) def buttonClicked(self): # 获取发送信号的按钮对象 sender = self.sender() # 根据按钮对象进行相应处理 if sender == self.button1: print("Button 1 clicked") elif sender == self.button2: print("Button 2 clicked") elif sender == self.button3: print("Button 3 clicked") if __name__ == '__main__': app = QApplication(sys.argv) widget = MyWidget() widget.show() sys.exit(app.exec_()) ``` 在这个示例中,我们创建了三个QPushButton对象,并将它们添加到一个QVBoxLayout布局中。然后,我们将每个按钮的clicked信号连接到一个名为buttonClicked的。在中,我们使用sender()方法获取发送信号的按钮对象,并根据该对象进行相应处理。 当您运行此示例时,单击任何一个按钮都会在控制台中输出相应的消息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

la_vie_est_belle

谢谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值