Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.
Cách dùng lớp QDockWidget của PyQt để tạo một widget
Trong giao diện người dùng (GUI) với PyQt, lớp QDockWidget là một công cụ hữu ích để tạo ra các cửa sổ phụ có thể linh hoạt gắn vào hoặc tách rời khỏi cửa sổ chính. Với QDockWidget, bạn có thể cung cấp cho người dùng khả năng tùy chỉnh bố cục ứng dụng, cho phép di chuyển, ẩn/hiện, hoặc nổi các widget trong các khu vực khác nhau của cửa sổ chính. Trong bài viết này, mìnhsẽ tìm hiểu cách sử dụng QDockWidget để tạo ra các widget có thể gắn hoặc nổi, từ đó xây dựng giao diện người dùng linh hoạt và tương tác hơn trong PyQt.
Giới thiệu về lớp QDockWidget trong PyQt
Lớp QDockWidget cho phép bạn tạo một widget có thể được gắn (dock) bên trong QMainWindow hoặc có thể được tách rời để trở thành một cửa sổ riêng.
Ví dụ về QDockWidget - Editor
Một QDockWidget có một thanh tiêu đề và một khu vực nội dung. Thanh tiêu đề hiển thị tiêu đề của widget, cùng với các nút như float (để tách rời) và close (để đóng widget).
Để tạo một dock widget và thêm nó vào cửa sổ chính, bạn thực hiện các bước sau:
Bài viết này được đăng tại [free tuts .net]
-
Đầu tiên, tạo một dock widget bằng cách sử dụng lớp QDockWidget:
dock = QDockWidget(tên_widget)
Sau đó, thiết lập các tính năng cho dock widget bằng phương thức setFeatures() của đối tượng QDockWidget. Ví dụ, bạn có thể vô hiệu hóa tất cả các tính năng docking như sau:
dock.setFeatures(QDockWidget.DockWidgetFeature.NoDockWidgetFeatures)
Cuối cùng, thêm dock widget vào cửa sổ chính bằng phương thức addDockWidget(). Ví dụ, để thêm dock widget vào khu vực bên trái của cửa sổ chính, bạn làm như sau:
self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, dock)
Lúc này, dock widget sẽ trống. Để thêm các widget con vào dock widget, bạn cần bọc các widget con bên trong một QWidget và sử dụng phương thức setWidget() của QDockWidget để thêm nó vào:
# Tạo một widget widget = QWidget() # Thêm các widget con vào widget chính # ... # Đặt widget vào dock widget dock.setWidget(widget)
Nếu dock widget bị đóng, bạn có thể hiển thị lại nó bằng phương thức show():
dock.show()
Ví dụ tạo một dock widget cho ứng dụng Text Editor
Dưới đây là một ví dụ về việc tạo một dock widget cho chương trình Text Editor:
import sys from pathlib import Path from PyQt6.QtWidgets import (QApplication, QMainWindow, QTextEdit, QFileDialog, QMessageBox, QToolBar, QLabel, QDockWidget, QWidget, QFormLayout, QLineEdit, QPushButton) from PyQt6.QtGui import QIcon, QAction from PyQt6.QtCore import QSize, Qt class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.setWindowIcon(QIcon('./assets/editor.png')) self.setGeometry(100, 100, 500, 300) self.title = 'Editor' self.filters = 'Text Files (*.txt)' self.set_title() self.path = None # Khởi tạo QTextEdit cho việc chỉnh sửa văn bản self.text_edit = QTextEdit(self) self.text_edit.textChanged.connect(self.text_changed) self.setCentralWidget(self.text_edit) # Menu bar menu_bar = self.menuBar() file_menu = menu_bar.addMenu('&File') edit_menu = menu_bar.addMenu('&Edit') view_menu = menu_bar.addMenu('&View') help_menu = menu_bar.addMenu('&Help') # Tạo các action cho menu new_action = QAction(QIcon('./assets/new.png'), '&New', self) new_action.setStatusTip('Tạo tài liệu mới') new_action.setShortcut('Ctrl+N') new_action.triggered.connect(self.new_document) file_menu.addAction(new_action) open_action = QAction(QIcon('./assets/open.png'), '&Open...', self) open_action.triggered.connect(self.open_document) open_action.setStatusTip('Mở tài liệu') open_action.setShortcut('Ctrl+O') file_menu.addAction(open_action) save_action = QAction(QIcon('./assets/save.png'), '&Save', self) save_action.setStatusTip('Lưu tài liệu') save_action.setShortcut('Ctrl+S') save_action.triggered.connect(self.save_document) file_menu.addAction(save_action) file_menu.addSeparator() exit_action = QAction(QIcon('./assets/exit.png'), '&Exit', self) exit_action.setStatusTip('Thoát ứng dụng') exit_action.setShortcut('Alt+F4') exit_action.triggered.connect(self.quit) file_menu.addAction(exit_action) undo_action = QAction(QIcon('./assets/undo.png'), '&Undo', self) undo_action.setStatusTip('Hoàn tác') undo_action.setShortcut('Ctrl+Z') undo_action.triggered.connect(self.text_edit.undo) edit_menu.addAction(undo_action) redo_action = QAction(QIcon('./assets/redo.png'), '&Redo', self) redo_action.setStatusTip('Làm lại') redo_action.setShortcut('Ctrl+Y') redo_action.triggered.connect(self.text_edit.redo) edit_menu.addAction(redo_action) view_search_action = QAction(QIcon('./assets/search.png'),'Search',self) view_search_action.setStatusTip('Hiển thị dock tìm kiếm') view_search_action.setShortcut('Ctrl+F') view_search_action.triggered.connect(self.show_search_dock) view_menu.addAction(view_search_action) about_action = QAction(QIcon('./assets/about.png'), 'About', self) help_menu.addAction(about_action) about_action.setStatusTip('Thông tin ứng dụng') about_action.setShortcut('F1') # Thanh công cụ (toolbar) toolbar = QToolBar('Main ToolBar') self.addToolBar(toolbar) toolbar.setIconSize(QSize(16, 16)) toolbar.addAction(new_action) toolbar.addAction(save_action) toolbar.addAction(open_action) toolbar.addSeparator() toolbar.addAction(undo_action) toolbar.addAction(redo_action) toolbar.addSeparator() toolbar.addAction(exit_action) # Thanh trạng thái (status bar) self.status_bar = self.statusBar() self.status_bar.showMessage('Sẵn sàng', 5000) self.character_count = QLabel("Chiều dài: 0") self.status_bar.addPermanentWidget(self.character_count) # Dock widget cho tìm kiếm self.dock = QDockWidget('Tìm kiếm') self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self.dock) search_form = QWidget() layout = QFormLayout(search_form) search_form.setLayout(layout) self.search_term = QLineEdit(search_form) self.search_term.setPlaceholderText("Nhập từ khóa tìm kiếm") layout.addRow(self.search_term) btn_search = QPushButton('Tìm', clicked=self.search) layout.addRow(btn_search) self.dock.setWidget(search_form) self.show() def show_search_dock(self): self.dock.show() def search(self): term = self.search_term.text() if not term: return cur = self.text_edit.find(term) if not cur: self.status_bar.showMessage(f'Không tìm thấy từ "{term}"', 2000) def set_title(self, filename=None): title = f"{filename if filename else 'Untitled'} - {self.title}" self.setWindowTitle(title) def confirm_save(self): if not self.text_edit.document().isModified(): return True message = f"Bạn có muốn lưu thay đổi cho {self.path if self.path else 'Untitled'}?" MsgBoxBtn = QMessageBox.StandardButton.Save | QMessageBox.StandardButton.Discard | QMessageBox.StandardButton.Cancel button = QMessageBox.question(self, self.title, message, buttons=MsgBoxBtn) if button == QMessageBox.StandardButton.Cancel: return False if button == QMessageBox.StandardButton.Save: self.save_document() return True def new_document(self): if self.confirm_save(): self.text_edit.clear() self.set_title() def write_file(self): self.path.write_text(self.text_edit.toPlainText()) self.statusBar().showMessage('Tập tin đã được lưu...', 3000) def save_document(self): if self.path: return self.write_file() filename, _ = QFileDialog.getSaveFileName(self, 'Lưu tập tin', filter=self.filters) if not filename: return self.path = Path(filename) self.write_file() self.set_title(filename) def open_document(self): filename, _ = QFileDialog.getOpenFileName(self, filter=self.filters) if filename: self.path = Path(filename) self.text_edit.setText(self.path.read_text()) self.set_title(filename) def quit(self): if self.confirm_save(): self.destroy() def text_changed(self): text = self.text_edit.toPlainText() self.character_count.setText(f'Chiều dài: {len(text)}') if __name__ == '__main__': app = QApplication(sys.argv) window = MainWindow() app.exec()
Cách hoạt động
Đầu tiên, tạo một dock widget và đặt tiêu đề của nó là ‘Search’:
self.dock = QDockWidget('Search')
Tiếp theo, thêm dock widget vào khu vực gắn bên trái cửa sổ chính:
self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, dock)
Sau đó, tạo một form tìm kiếm sẽ được thêm vào dock widget:
search_form = QWidget() layout = QFormLayout(search_form) search_form.setLayout(layout) self.search_term = QLineEdit(search_form) self.search_term.setPlaceholderText("Enter a search term") layout.addRow(self.search_term) btn_search = QPushButton('Go', clicked=self.search) layout.addRow(btn_search)
Sau đó, thêm form tìm kiếm vào dock widget:
self.dock.setWidget(search_form)
Cuối cùng, khi người dùng nhập một từ khóa tìm kiếm và nhấp vào nút "Go", chúng ta sử dụng phương thức find()
của QTextEdit
để tìm kiếm văn bản:
Kết bài
QDockWidget là một thành phần mạnh mẽ giúp bạn tạo các khu vực có thể gắn hoặc thả rời khỏi cửa sổ chính, cung cấp cho người dùng sự linh hoạt khi sử dụng ứng dụng. Với ví dụ trong hướng dẫn, chúng ta đã tạo thành công khu vực tìm kiếm bên trái cửa sổ chính và tích hợp thêm thanh công cụ, menu, cùng các tính năng chỉnh sửa như undo/redo để tăng cường trải nghiệm người dùng. Hãy thử chạy ứng dụng để kiểm tra cách các thành phần này hoạt động và xem cách dock widget có thể giúp cải thiện tính tương tác và hiệu quả của giao diện người dùng trong các ứng dụng PyQt.