pyqt---------事件与信号处理

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槽连接在一起。

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

Signal & slotFigure: 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()方法判断发送信号的信号源是哪一个。然后在应用的状态栏上显示被按下的按钮的标签内容。

Event senderFigure: 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教程中,我们概览了信号了槽机制。

原文地址:https://www.cnblogs.com/icat-510/p/10106972.html