События и сигналы в PyQt5
События
Все GUI приложения основаны на обработке событий. В основном события создаются пользователем приложения. Но могут создаваться и другими источниками: например интернет соединением, управлением окон или таймером. Когда мы вызываем метод приложенияexec_()
,
приложение запускает основную цикл.
Основной цикл загружает события и
посылает их к объектам.
В модели событий существует три участника:
-
событие источник
-
событие объект
-
событие цель
У PyQt5 уникальный механизм работы с событиями — это сигналы (signal) и слоты (slot). Сигналы и слоты используются для связи между объектами. Сигнал выпускается когда конкретное событие возникает. Слотом может быть все, что можно вызвать на языке Python. Слот вызывается когда связанный с ним сигнал появляется.
Сигналы и слоты
Это простой пример демонстрирующий сигналы и слоты в PyQt5.
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode PyQt5 tutorial
В этом примере мы связываем сигнал от QSlider к слоту в 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(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
В примере мы выводим на экран
QtGui.QLCDNumber
и QtGui.QSlider
.
Мы изменяем число lcd
перетаскивая мышкой кнопку ползунка.
sld.valueChanged.connect(lcd.display)Здесь мы соединяем сигнал
valueChanged
ползунка со слотом ИЗОБРАЖЕНИЯ числа
lcd
.
Тот кто посылает это объект, посылающий сигнал. Получатель, это объект получающий сигнал. Слот это метод, который реагирует на сигнал.
Figure: Signal & slot
Переписывание обработчика событий
События в PyQt5 часто обрабатывают переделывая обработку событий.
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode PyQt5 tutorial
В этом примере мы переделываем обработку событий.
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()
.
def keyPressEvent(self, e): if e.key() == Qt.Key_Escape: self.close()
Посылающий событие
Иногда очень удобно знать какое виджет послал сигнал. Для этого, PyQt5 имеет методsender()
.
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode PyQt5 tutorial
В этом примере мы определяем объект посылающий событие.
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_())
Мы имеем две кнопки. В методе buttonClicked()
мы определяем какая кнопка была нажата
при помощи метода sender()
.
btn1.clicked.connect(self.buttonClicked) btn2.clicked.connect(self.buttonClicked)Обе кнопки присоединены к одному и тому же слоту.
def buttonClicked(self): sender = self.sender() self.statusBar().showMessage(sender.text() + ' was pressed')Мы определили источник сигнала вызывая метод
sender()
. В строке
состояния мы показали наименование
нажатой кнопки.
Figure: Event sender
Создание сигналов
Объекты, порожденные отQObject
могут порождать сигналы. В следующем
примере мы увидим как мы можем создать
пользовательский сигнал.
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode PyQt5 tutorial
В этом примере мы покажем как создать сигнал.
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
.
Этот сигнал инициируется во время
события нажатия мыши. Этот сигнал
связывается со слотом close()
объекта QMainWindow
.
class Communicate(QObject): closeApp = pyqtSignal()Сигнал создается методом
pyqtSignal()
как атрибут расширения класса Communicate
.
Этот метод принадлежит классу Qobject.self.c = Communicate() self.c.closeApp.connect(self.close)Пользовательский сигнал
closeApp
подключается к слоту close()
сласса QMainWindow
.
def mousePressEvent(self, event): self.c.closeApp.emit()Когда мы нажимаем на окне мышкой, создается сигнал
closeApp
.
Приложение заканчивается.
Комментариев нет:
Отправить комментарий