Обычно скрипт Python выполняется сверху вниз следующим образом:
- Получить исходные данные.
- Обрабатывать входные данные для получения выходных данных.
- Вывести результаты на экран или в файл.
Это называется процедурным программированием.
Когда вы создаете программу GUI, вы используете вместо этого событийно-управляемое программирование. В парадигме событийно-управляемого программирования программа имеет следующий поток:
- Создавайте виджеты, такие как метки, строки редактирования и кнопки.
- Запустите цикл событий, ожидающий событий.
- Реагируйте на события по мере их возникновения, выполняя вызываемые функции.
Обратите внимание, что вызываемый объект — это функция, метод или объект, реализующий метод __call__().
Что такое сигналы и слоты PyQT?
Для связи событий с вызываемыми объектами программы PyQt использует механизм сигналов и слотов в Python.
Сигналы
Сигнал — это особое свойство объекта, которое выдается при возникновении события. Событием может быть действие пользователя, тайм-аут или завершение асинхронной операции.
Слоты
Слот — это вызываемый объект, который может принимать сигнал и реагировать на него. Чтобы реагировать на события, вы подключаете сигналы к слотам. Когда вы подключаете сигнал к слоту, слот будет выполняться при испускании сигнала.
В PyQt все подклассы класса QObject могут отправлять и получать сигналы. Почти все классы в PyQt являются подклассами класса QObject.
Давайте рассмотрим пример, чтобы понять, как работает механизм сигналов и слотов PyQt.
Пример сигналов и слотов PyQt
Следующая программа отображает окно с кнопкой. Когда вы нажимаете кнопку, программа показывает сообщение о нажатии в консоли:
import sys
from PyQt6.QtWidgets import(
QApplication,
QWidget,
QLineEdit,
QPushButton,
QVBoxLayout
)
class MainWindow(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# set the window title
self.setWindowTitle('Qt Signals & Slots')
# create a button widget and connect its clicked signal
# to a method
button = QPushButton('Click me')
button.clicked.connect(self.button_clicked)
# place the buton on window using a vertical box layout
layout = QVBoxLayout()
self.setLayout(layout)
layout.addWidget(button)
# show the window
self.show()
def button_clicked(self):
print('clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
# create the main window and display it
window = MainWindow()
# start the event loop
sys.exit(app.exec())
Как это работает (мы сосредоточимся только на сигналах и слотах).
- Сначала создайте кнопку с помощью виджета QPushButton:
button = QPushButton('Click me')
- Во-вторых, подключите сигнал clicked к методу on_clicked(слоту):
button.clicked.connect(self.button_clicked)
В общем случае синтаксис подключения сигнала к слоту выглядит следующим образом:
sender_object.signal_name.connect(receiver_object.slot_name)
Также вы можете подключить сигнал к слоту, передавая слот сигналу в качестве ключевого аргумента. Например:
button = QPushButton('Click me', clicked=self.button_clicked)
В-третьих, определите метод on_clicked, который выводит сообщение о щелчке на терминал:
def on_clicked(self):
print('clicked')
При нажатии кнопки QPushButton излучает сигнал clicked, который запускает подключенный слот on_clicked.
Обратите внимание, что следующий код размещает кнопку в окне, используя вертикальную компоновку.
layout = QVBoxLayout() self.setLayout(layout) layout.addWidget(button)
Использование сигналов, отправляющих данные
Сигнал может переносить данные, которые предоставляют состояние объекта при возникновении события. Например, сигнал textChanged QLineEdit содержит текст, введенный в виджет.
Если сигнал несет данные, подключенный слот может их принять.
Следующая программа показывает виджеты QLineEdit и QLabel. Когда вы печатаете что-то в QLineEdit, QLabel отобразит это соответствующим образом:
import sys
from PyQt6.QtWidgets import(
QApplication,
QWidget,
QLabel,
QLineEdit,
QVBoxLayout
)
class MainWindow(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setWindowTitle('Qt Signals & Slots')
# create widgets
label = QLabel()
line_edit = QLineEdit()
line_edit.textChanged.connect(label.setText)
# place the widgets
layout = QVBoxLayout()
layout.addWidget(label)
layout.addWidget(line_edit)
self.setLayout(layout)
# show the window
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec())
Как это работает.
- Сначала создайте виджет QLabel. Виджет QLabel имеет метод setText(), который устанавливает его содержимое.
label = QLabel()
- Во-вторых, создайте новый виджет QLineEdit:
line_edit = QLineEdit()
- В-третьих, подключите сигнал textChanged к методу setText объекта QLabel:
line_edit.textChanged.connect(label.setText)
Когда вы печатаете что-либо в QLineEdit:
- Сигнал textChanged отправляет текст.
- QLabel получает текст и передает его методу setText().
