pyqt:信号与槽的关系

GUI应用程序是事件驱动的。 事件主要由应用程序的用户生成。 但它们也可以通过其他手段产生,例如:网络连接,窗口管理器或定时器。 当我们调用应用程序的exec_()方法时,应用程序进入主循环。 主循环获取事件并将其发送到对象。

在事件模型中,有三个参与者:

  • 事件来源
  • 事件对象
  • 事件目标

事件源是其状态更改的对象。 它会生成事件。 事件对象(event)将状态更改封装在事件源中。 事件目标是要通知的对象。 事件源对象将处理事件的任务委托给事件目标。

import sys
from PyQt5.QtWidgets import (QApplication, QLabel, QWidget, QMessageBox)
from PyQt5.QtGui import QPainter, QColor, QPen
from PyQt5.QtCore import Qt
from PyQt5.QtCore import pyqtSignal,QObject
class Example(QWidget):
distance_from_center = 0
def __init__(self):
super().__init__()
self.initUI()
# self.setMouseTracking(True)
def initUI(self):
self.setGeometry(200, 200, 1000, 500)
self.setWindowTitle('学点编程吧')
self.label = QLabel(self)
self.label.resize(500, 40)
self.show()
self.pos = None def mouseMoveEvent(self, event):
distance_from_center = round(((event.y() - 250)**2 + (event.x() - 500)**2)**0.5)
self.label.setText('坐标: ( x: %d ,y: %d )' % (event.x(), event.y()) + " 离中心点距离: " + str(distance_from_center))
self.pos = event.pos()
self.update() def paintEvent(self, event):
if self.pos:
q = QPainter(self)
q.drawLine(500, 250, self.pos.x(), self.pos.y()) # 自定义信号
class Signal(QObject):
# 自定义一个信号
showmouse = pyqtSignal() class Example1(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(200, 200, 300, 300)
self.setWindowTitle('学点编程吧') self.s = Signal()
self.s.showmouse.connect(self.about) self.show() def about(self):
QMessageBox.about(self, '鼠标', '你点鼠标了吧!') def mousePressEvent(self, e):
self.s.showmouse.emit() if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example1()
sys.exit(app.exec_())

事件源是状态发生改变的对象。它产生了事件。事件对象(evnet)封装了事件源中的状态变化。事件目标是想要被通知的对象。事件源对象代表了处理一个事件直到事件目标做出响应的任务。

PyQt5有一个独一无二的信号和槽机制来处理事件。信号和槽用于对象之间的通信。当指定事件发生,一个事件信号会被发射。槽可以被任何Python脚本调用。当和槽连接的信号被发射时,槽会被调用。

事件源是状态发生改变的对象。它产生了事件。事件对象(evnet)封装了事件源中的状态变化。事件目标是想要被通知的对象。事件源对象代表了处理一个事件直到事件目标做出响应的任务。

PyQt5有一个独一无二的信号和槽机制来处理事件。信号和槽用于对象之间的通信。当指定事件发生,一个事件信号会被发射。槽可以被任何Python脚本调用。当和槽连接的信号被发射时,槽会被调用。

信号 & 槽

这个例子演示了PyQt5中的信号和槽的使用。

#!/usr/bin/python3
# -*- coding: utf-8 -*-
 
"""
ZetCode PyQt5 tutorial
 
In this example, we connect a signal
of a QSlider to a slot of a QLCDNumber.
 
author: Jan Bodnar
website: zetcode.com
last edited: January 2015
"""
 
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider, 
    QVBoxLayout, QApplication)
 
 
class Example(QWidget):
     
    def __init__(self):
        super().__init__()
         
        self.initUI()
         
         
    def initUI(self):
         
        lcd = QLCDNumber(self)
        sld = QSlider(Qt.Horizontal, self)
 
        vbox = QVBoxLayout()
        vbox.addWidget(lcd)
        vbox.addWidget(sld)
 
        self.setLayout(vbox)
        sld.valueChanged.connect(lcd.display)
         
        self.setGeometry(300300250150)
        self.setWindowTitle('Signal & slot')
        self.show()
         
 
if __name__ == '__main__':
     
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
   

在我们的例子中,我们显示了一个QtGui.QLCDNumber和一个QtGui.QSlider类。我们拖动滑块条的把手,lcd数字会变化。

1
sld.valueChanged.connect(lcd.display)

  

这里,我们将滑块条的valueChanged信号和lcd数字显示的display槽连接在一起。

发送者是一个发送了信号的对象。接受者是一个接受了信号的对象。槽是对信号做出反应的方法。

Figure: Signal & slot

重写事件处理函数

PyQt中的事件处理通常通过重写事件处理函数来处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/usr/bin/python3
# -*- coding: utf-8 -*-
 
"""
ZetCode PyQt5 tutorial
 
In this example, we reimplement an
event handler.
 
author: Jan Bodnar
website: zetcode.com
last edited: January 2015
"""
 
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QApplication
 
 
class Example(QWidget):
     
    def __init__(self):
        super().__init__()
         
        self.initUI()
         
         
    def initUI(self):     
         
        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Event handler')
        self.show()
         
         
    def keyPressEvent(self, e):
         
        if e.key() == Qt.Key_Escape:
            self.close()
         
         
if __name__ == '__main__':
     
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

在我们的例子中,我们重写了keyPressEvent()事件处理函数。

1
2
3
4
def keyPressEvent(self, e):
     
    if e.key() == Qt.Key_Escape:
        self.close()

如果我们点击了Esc按钮,应用将会被终止。

事件发送者

有时需要方便的知道哪一个组件是信号发送者。因此,PyQt5拥有了sender()方法来解决这个问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#!/usr/bin/python3
# -*- coding: utf-8 -*-
 
"""
ZetCode PyQt5 tutorial
 
In this example, we determine the event sender
object.
 
author: Jan Bodnar
website: zetcode.com
last edited: January 2015
"""
 
import sys
from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication
 
 
class Example(QMainWindow):
     
    def __init__(self):
        super().__init__()
         
        self.initUI()
         
         
    def initUI(self):     
 
        btn1 = QPushButton("Button 1", self)
        btn1.move(30, 50)
 
        btn2 = QPushButton("Button 2", self)
        btn2.move(150, 50)
       
        btn1.clicked.connect(self.buttonClicked)           
        btn2.clicked.connect(self.buttonClicked)
         
        self.statusBar()
         
        self.setGeometry(300, 300, 290, 150)
        self.setWindowTitle('Event sender')
        self.show()
         
         
    def buttonClicked(self):
       
        sender = self.sender()
        self.statusBar().showMessage(sender.text() + ' was pressed')
         
         
if __name__ == '__main__':
     
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

在我们的例子中,我们有两个按钮。在buttonClikced()方法中,我们调用sender()方法来判断哪一个按钮是我们按下的。

1
2
btn1.clicked.connect(self.buttonClicked)           
btn2.clicked.connect(self.buttonClicked)

两个按钮都连接到了同一个槽中。

1
2
3
4
def buttonClicked(self):
   
    sender = self.sender()
    self.statusBar().showMessage(sender.text() + ' was pressed')

我们调用sender()方法判断发送信号的信号源是哪一个。然后在应用的状态栏上显示被按下的按钮的标签内容。

Figure: Event sender

发送信号

从QObejct生成的对象可以发送信号。在下面的例子中我们将会看到怎样去发送自定义的信号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!/usr/bin/python3
# -*- coding: utf-8 -*-
 
"""
ZetCode PyQt5 tutorial
 
In this example, we show how to emit a
signal.
 
author: Jan Bodnar
website: zetcode.com
last edited: January 2015
"""
 
import sys
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtWidgets import QMainWindow, QApplication
 
 
class Communicate(QObject):
     
    closeApp = pyqtSignal()
     
 
class Example(QMainWindow):
     
    def __init__(self):
        super().__init__()
         
        self.initUI()
         
         
    def initUI(self):     
 
        self.c = Communicate()
        self.c.closeApp.connect(self.close)      
         
        self.setGeometry(300, 300, 290, 150)
        self.setWindowTitle('Emit signal')
        self.show()
         
         
    def mousePressEvent(self, event):
         
        self.c.closeApp.emit()
         
         
if __name__ == '__main__':
     
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

我们创建一个新的信号叫做closeApp。当触发鼠标点击事件时信号会被发射。信号连接到了QMainWindow的close()方法。

1
2
3
class Communicate(QObject):
     
    closeApp = pyqtSignal()

信号使用了pyqtSignal()方法创建,并且成为外部类Communicate类的属性。

1
2
self.c = Communicate()
self.c.closeApp.connect(self.close)
   

把自定义的closeApp信号连接到QMainWindow的close()槽上。

1
2
3
def mousePressEvent(self, event):
     
    self.c.closeApp.emit()

当我们在窗口上点击一下鼠标,closeApp信号会被发射。应用中断。

这部分的PyQt5教程中,我们概览了信号了槽机制。

pyqt---------事件与信号处理的更多相关文章

  1. 第15.17节 PyQt(Python+Qt)入门学习:PyQt图形界面应用程序的事件捕获方法大全及对比分析

    老猿Python博文目录 老猿Python博客地址 按照老猿规划的章节安排,信号和槽之后应该介绍事件,但事件在前面的随笔<PyQt(Python+Qt)实现的GUI图形界面应用程序的事件捕获方法 ...

  2. PyQt(Python+Qt)实现的GUI图形界面应用程序的事件捕获方法大全及对比分析

    一. 概述 PyQt的图形界面应用中,事件处理类似于Windows系统的消息处理.一个带图形界面的应用程序启动后,事件处理就是应用的主循环,事件处理负责接收事件.分发事件.接收应用处理事件的返回结果, ...

  3. Qt事件和信号的区别 .

    仔细来看,事件与信号其实并无多大差别,从我们对其需求上来说,都只要能注册事件或信号响应函数,在事件或信号产生时能够被通知到即可.但有一项区别在于,事件处理函数的返回值是有意义的,我们要根据这个返回值来 ...

  4. study notes: high performance linux server programming

    1:linux网络API分为:socker地址API,socker基础API,网络信息API 1,socker地址API:包含IP地址和端口(ip, port).表示TCP通信的一端. 2,socke ...

  5. 服务器编程入门(10)TCP回射服务器实现 - 并发

    问题聚焦:     在前面我们大概浏览了一下服务器编程需要掌握的一些知识和技术,以及架构思想.        实践,才是检验真理的唯一标准..从这节起我们将在这些技术的基础上,一步步实现以及完善一个服 ...

  6. 两种高性能 I/O 设计模式 Reactor 和 Proactor

    两种高性能 I/O 设计模式 Reactor 和 Proactor Reactor 和 Proactor 是基于事件驱动,在网络编程中经常用到两种设计模式. 曾经在一个项目中用到了网络库 libeve ...

  7. Linux高性能server编程——信号及应用

     信号 信号是由用户.系统或者进程发送给目标进程的信息.以通知目标进程某个状态的改变或系统异常. Linux信号可由例如以下条件产生: 对于前台进程.用户能够通过输入特殊的终端字符来给它发送信号. ...

  8. linux中的信号机制

    概述 Linux信号机制是在应用软件层次上对中断机制的一种模拟,信号提供了一种处理异步事件的方法,例如,终端用户输入中断键(ctrl+c),则会通过信号机制停止一个程序[1]. 这其实就是向那个程序( ...

  9. 【pyqtgraph绘图】Qt速成课程

    解读官方API-Qt速成课程 参考:http://www.pyqtgraph.org/documentation/qtcrashcourse.html Qt速成课程 PyQtGraph广泛使用Qt来生 ...

  10. qt线程(转)----这篇很专业!

    本文档是自己所整理的一份文档,部分是原创,还转贴了网上的一此资料(已经标明了),(难点是多线程的编写),是有源代码的,大家可以作为参考,用到的知识是视频采集,压缩解压(xvid),实时传输(jrtp) ...

随机推荐

  1. [转] Ubuntu16.04完美安装Sublime text3

    转载自:https://www.cnblogs.com/hupeng1234/p/6957623.html 1.安装方法 1)使用ppa安装 sudo add-apt-repository ppa:w ...

  2. C# 实现CRC16校验

    前言 本文将使用一个NuGet公开的组件技术来实现CRC16校验功能,提供了一些简单的API,来方便的实现. 在Visual Studio 中的NuGet管理器中可以下载安装,也可以直接在NuGet控 ...

  3. linux ipv6开启的配置文件

    1./etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0TYPE=EthernetUUID=9d1d6e2a-cfc5-4e60-8f28-b77 ...

  4. vim选中多行缩进(python多行缩进)与删除多行前面的空格

    最近用vim写python,有时候会在一段代码前面套一个循环的操作,这个时候将这一段代码整体向后平移四个空格,来满足vim缩进的要求,如何做到这一点呢? 1. ESC之后,ctrl+v进入多行行首选中 ...

  5. Date.parse()转化日期为时间戳,ios与Android兼容写法

    把固定格式日期转化为时间戳: //格式化当地日期 new Date('2017-11-11 0:0:0') //结果为:Sat Nov 11 2017 00:00:00 GMT+0800 (中国标准时 ...

  6. 02bootstrap_通用标签样式和代码

    ---恢复内容开始--- 02bootstrap_通用标签样式和代码 1.标题:page-header 副标题样式 2.常用标签和样式 Bootstrap 将全局 font-size 设置为 14px ...

  7. c#读sql server数据添加到MySQL数据库

    using System;using System.Collections.Generic;using System.Text;using Console = System.Console;using ...

  8. nginx配置http强制跳转https

    nginx配置http强制跳转https 网站添加了https证书后,当http方式访问网站时就会报404错误,所以需要做http到https的强制跳转设置. 一.采用nginx的rewrite方法 ...

  9. 读取 exe dll 自定义config 文件

    ExeConfigurationFileMap map = new ExeConfigurationFileMap(); map.ExeConfigFilename = GPARAM._configF ...

  10. E212: Can't open file for writing Press ENTER or type command to continue

    E212: Can't open file for writing Press ENTER or type command to continue 出现这个错误的原因可能有两个: 1.当前用户的权限不 ...