Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.
Tín hiệu và Khe (Signals & Slots) trong PyQt
Trong lập trình giao diện đồ họa, việc phản hồi linh hoạt và nhanh chóng các sự kiện từ người dùng là điều cốt yếu để tạo ra những ứng dụng mượt mà và thân thiện. PyQt, một trong những thư viện phổ biến nhất để xây dựng giao diện đồ họa trong Python, cung cấp một cơ chế mạnh mẽ gọi là tín hiệu (signals) và khe (slots) để xử lý các sự kiện. Trong bài viết này, bạn sẽ tìm hiểu cách thức hoạt động của tín hiệu và khe trong PyQt, cũng như cách sử dụng chúng để tạo ra các ứng dụng GUI tương tác và hiệu quả.
Giới thiệu về tín hiệu và khe trong PyQt
Thông thường, một tập lệnh Python sẽ chạy từ đầu đến cuối theo trình tự sau:
- Lấy đầu vào.
- Xử lý đầu vào để tạo ra kết quả.
- Xuất kết quả ra màn hình hoặc ghi vào tệp.
Đây được gọi là lập trình thủ tục (procedural programming).
Khi bạn tạo một chương trình giao diện đồ họa (GUI), bạn sẽ sử dụng lập trình hướng sự kiện (event-driven programming) thay vì lập trình thủ tục. Trong lập trình hướng sự kiện, chương trình sẽ có luồng xử lý như sau:
Bài viết này được đăng tại [free tuts .net]
- Tạo các thành phần giao diện như nhãn, ô nhập liệu, và các nút.
- Bắt đầu một vòng lặp sự kiện để chờ đợi các sự kiện xảy ra.
- Phản hồi lại các sự kiện khi chúng xảy ra bằng cách thực thi các hàm gọi lại (callables).
Trong PyQt, cơ chế để kết nối các sự kiện với các hàm gọi lại này được gọi là tín hiệu và khe.
Tín hiệu (Signals)
Tín hiệu là một thuộc tính đặc biệt của một đối tượng được phát ra khi một sự kiện xảy ra. Sự kiện có thể là hành động của người dùng, một khoảng thời gian chờ hết hạn, hoặc việc hoàn thành một thao tác bất đồng bộ.
Khe (Slots)
Khe là một callable (hàm hoặc phương thức) có thể nhận tín hiệu và phản hồi lại tín hiệu đó.
Để phản hồi lại các sự kiện, bạn kết nối tín hiệu với khe. Khi tín hiệu được phát ra, khe sẽ được thực thi.
Trong PyQt, tất cả các lớp con của lớp QObject
đều có thể phát và nhận tín hiệu. Hầu hết các lớp trong PyQt đều là các lớp con của QObject
.
Hãy xem một ví dụ để hiểu cách hoạt động của cơ chế tín hiệu và khe trong PyQt.
Ví dụ về tín hiệu và khe trong PyQt
Chương trình dưới đây sẽ hiển thị một cửa sổ có một nút bấm. Khi bạn nhấn nút, chương trình sẽ hiển thị thông báo "clicked" trên bảng điều khiển:
import sys from PyQt6.QtWidgets import ( QApplication, QWidget, QPushButton, QVBoxLayout ) class MainWindow(QWidget): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Đặt tiêu đề cho cửa sổ self.setWindowTitle('Qt Signals & Slots') # Tạo một widget nút và kết nối tín hiệu 'clicked' # với một phương thức button = QPushButton('Click me') button.clicked.connect(self.button_clicked) # Đặt nút vào cửa sổ sử dụng layout dạng hộp dọc layout = QVBoxLayout() self.setLayout(layout) layout.addWidget(button) # Hiển thị cửa sổ self.show() def button_clicked(self): print('clicked') if __name__ == '__main__': app = QApplication(sys.argv) # Tạo cửa sổ chính và hiển thị nó window = MainWindow() # Bắt đầu vòng lặp sự kiện sys.exit(app.exec())
Cách hoạt động của tín hiệu và khe trong ví dụ trên
Đầu tiên, tạo một nút bấm sử dụng widget QPushButton
:
button = QPushButton('Click me')
Sau đó, kết nối tín hiệu clicked
với phương thức button_clicked
:
button.clicked.connect(self.button_clicked)
Cú pháp chung để kết nối một tín hiệu với một khe như sau:
sender_object.signal_name.connect(receiver_object.slot_name)
Bạn cũng có thể kết nối tín hiệu với khe bằng cách truyền khe vào tín hiệu như một đối số keyword:
button = QPushButton('Click me', clicked=self.button_clicked)
Định nghĩa phương thức button_clicked
để in ra thông báo "clicked" khi nút được bấm:
def button_clicked(self): print('clicked')
Khi bạn nhấn nút, QPushButton
sẽ phát ra tín hiệu clicked
, và tín hiệu này sẽ kích hoạt khe button_clicked
.
Sử dụng tín hiệu để gửi dữ liệu trong PyQt
Một tín hiệu có thể mang theo dữ liệu, cung cấp trạng thái của đối tượng khi sự kiện xảy ra. Ví dụ, tín hiệu textChanged
của QLineEdit
chứa văn bản được nhập vào trong widget.Nếu một tín hiệu mang theo dữ liệu, khe kết nối với tín hiệu đó có thể nhận và xử lý dữ liệu.
Ví dụ sau đây cho thấy việc sử dụng QLineEdit
và QLabel
. Khi bạn nhập vào QLineEdit
, QLabel
sẽ hiển thị nội dung tương ứng:
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') # Tạo các widget label = QLabel() line_edit = QLineEdit() line_edit.textChanged.connect(label.setText) # Đặt các widget vào layout layout = QVBoxLayout() layout.addWidget(label) layout.addWidget(line_edit) self.setLayout(layout) # Hiển thị cửa sổ self.show() if __name__ == '__main__': app = QApplication(sys.argv) window = MainWindow() sys.exit(app.exec())
Cách hoạt động của ví dụ trên
Tạo một widget QLabel
. Widget QLabel
có phương thức setText()
để thiết lập nội dung của nó.
label = QLabel()
Tạo một widget QLineEdit
:
line_edit = QLineEdit()
Kết nối tín hiệu textChanged
với phương thức setText
của đối tượng QLabel
:
line_edit.textChanged.connect(label.setText)
Khi bạn nhập vào QLineEdit
, tín hiệu textChanged
sẽ gửi văn bản đến QLabel
và hiển thị nó.
Kết bài
Việc hiểu và sử dụng cơ chế tín hiệu và khe trong PyQt là một kỹ năng quan trọng giúp bạn xây dựng các ứng dụng GUI phức tạp và linh hoạt. Nhờ có tín hiệu và khe, bạn có thể dễ dàng kết nối các sự kiện với các hành động cụ thể, tạo nên trải nghiệm người dùng mượt mà và trực quan. Qua đó, PyQt không chỉ đơn thuần là một công cụ lập trình giao diện mà còn là một nền tảng mạnh mẽ để phát triển các ứng dụng có tính tương tác cao, đáp ứng nhanh chóng và chính xác nhu cầu của người dùng.