美文网首页
4.事件与信号

4.事件与信号

作者: 徐凯_xp | 来源:发表于2018-12-06 16:23 被阅读0次

所有的应用都是事件驱动的。事件大部分都是由用户的行为产生的,当然也有其他的事件产生方式,比如网络的连接,窗口管理器或者定时器等。调用应用的exec_()方法时,应用会进入主循环,主循环会监听和分发事件。

在事件模型中,有三个角色:

  • 事件源
  • 事件
  • 事件目标

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

PyQt5处理事件方面有个signal and slot机制。Signals and slots用于对象间的通讯。事件触发的时候,发生一个signal,slot是用来被Python调用的(相当于一个句柄,相当于事件的绑定函数)slot只有在事件触发的时候才能调用

Signals & slots(信号与槽)
#!/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 2017
"""

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(300, 300, 250, 150)
        self.setWindowTitle('Signal and slot')
        self.show()
        

if __name__ == '__main__':
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

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

  1. 这里,我们将滑块条的valueChanged信号和lcd数字显示的display槽连接在一起。
sld.valueChanged.connect(lcd.display)
  1. sender是信号的发送者,receiver是信号的接收者,slot是对这个信号应该做出的反应。

重写事件处理函数

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

#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
In this example, we reimplement an 
event handler. 
"""

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()

def keyPressEvent(self, e):
    
    if e.key() == Qt.Key_Escape:
        self.close()

如果我们点击了ESC按钮,应用就会退出

事件对象

事件对象是用python来描述一系列的事件自身属性的对象。

#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
ZetCode PyQt5 tutorial 

In this example, we display the x and y 
coordinates of a mouse pointer in a label widget.

Author: Jan Bodnar
Website: zetcode.com 
Last edited: August 2017
"""

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QApplication, QGridLayout, QLabel

class Example(QWidget):
    
    def __init__(self):
        super().__init__()
        
        self.initUI()
        
        
    def initUI(self):      
        
        grid = QGridLayout()
        grid.setSpacing(10)
        
        x = 0
        y = 0
        
        self.text = "x: {0},  y: {1}".format(x, y)
        
        self.label = QLabel(self.text, self)
        grid.addWidget(self.label, 0, 0, Qt.AlignTop)
        
        self.setMouseTracking(True)
        
        self.setLayout(grid)
        
        self.setGeometry(300, 300, 350, 200)
        self.setWindowTitle('Event object')
        self.show()
        
        
    def mouseMoveEvent(self, e):
        
        x = e.x()
        y = e.y()
        
        text = "x: {0},  y: {1}".format(x, y)
        self.label.setText(text)
    
        
if __name__ == '__main__':
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

在此示例中,我们在一个组件里显示鼠标的X和Y坐标

  1. X Y坐标显示在QLabel组件里
self.text = "x: {0},  y: {1}".format(x, y)
self.label = QLabel(self.text, self)
  1. 鼠标追踪默认没有开启,当有鼠标点击事件发生后才会开启。
self.setMouseTracking(True)

3.·e代表了事件对象。里面有我们触发事件(鼠标移动)的事件对象。x()y()方法得到鼠标的xy坐标点,然后拼成字符串输出到QLabel组件里。

def mouseMoveEvent(self, e):
    
    x = e.x()
    y = e.y()
    
    text = "x: {0},  y: {1}".format(x, y)
    self.label.setText(text)
事件发送人

有时候我们会想知道是哪个组件发出了一个信号,PyQt5里的sender()方法能搞定这件事。

#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
In this example, we determine the event sender
object.
"""

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_())

我们的示例中有两个按钮。在buttonClicked()方法中,我们通过调用sender()方法确定我们点击了哪个按钮 。

  1. 两个按钮都连接到同一个插槽(slot)。
btn1.clicked.connect(self.buttonClicked)            
btn2.clicked.connect(self.buttonClicked)
  1. 我们调用sender()方法判断发送信号的信号源是哪一个。然后在应用的状态栏上显示被按下的按钮的标签内容。
def buttonClicked(self):
    sender = self.sender()
    self.statusBar().showMessage(sender.text() + ' was pressed')
信号发送

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

#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
ZetCode PyQt5 tutorial 

In this example, we show how to 
emit a custom signal. 

Author: Jan Bodnar
Website: zetcode.com 
Last edited: August 2017
"""

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. 信号使用了pyqtSignal()方法创建,并且成为外部类Communicate类的属性。
class Communicate(QObject):
    closeApp = pyqtSignal()
  1. 自定义的closeApp信号连接到QMainWindow的close()槽上。
self.c = Communicate()
self.c.closeApp.connect(self.close) 
  1. 点击窗口的时候,发送closeApp信号,程序终止。
def mousePressEvent(self, event):
    self.c.closeApp.emit()

相关文章

  • 4.事件与信号

    所有的应用都是事件驱动的。事件大部分都是由用户的行为产生的,当然也有其他的事件产生方式,比如网络的连接,窗口管理器...

  • 事件与信号

    事件模型三个主要角色:事件源,事件,事件目标。 事件源:发生状态改变的对象(将处理事件任务委托给事件目标) 事件:...

  • 信号与槽(SIGNAL-SLOT)

    一、系统设置槽-信号 在QtCreator中建立槽信号事件 设置槽事件 设置信号事件 二、自定义槽信号事件 设置对...

  • DTK教程 七 :信号与槽 [ 就是我点一下按钮,按钮做什么事情

    信号与槽是Qt的特色,dtk使用了Qt的库,自然是拥有这个特色的。与事件相比较而言,我更喜欢信号与槽,主要是信号与...

  • 信号

    一个典型的信号处理与响应 摘要 1.信号基本概念2.信号产生的一般方式3.信号递达盒阻塞的概念和原理4.信号捕捉方...

  • js高级程序设计笔记21

    事件 1.event 2.事件类型 3.UI事件 4.焦点事件 5鼠标与滚轮事件 0 //主鼠标按钮1 //中间按...

  • Unix进程通信:信号

    信号原理 信号机制:事件促使内核向进程发送信号 事件类型:键盘按键请求内核产生信号:ctrl+c、ctrl+/等进...

  • Nodejs 信号

    前言 当Nodejs 进程接收一个信号时,会触发信号事件。我们通过man kill来查看所有的信号事件 常用信号解...

  • 2019-02-18 信号和信号槽

    PyQt5:PyQt5 信号与槽(PyQt5的事件处理机制) 一、事件 在事件模型,有三个参与者:事件源、事件目标...

  • QObject三大核心功能——内存管理

    信号与槽,内存管理,事件处理 QObject的parent or 对象树(Object Tree) QObject...

网友评论

      本文标题:4.事件与信号

      本文链接:https://www.haomeiwen.com/subject/bzqocqtx.html