Ở các bài học trước, Chúng ta đã dùng QComboBox, QListWidget để hiển thị dữ liệu dạng danh sách, tuy nhiên nó chưa được chi tiết hóa cho từng thuộc tính. QTableWidget là một widget dùng để hiển thị dữ liệu dạng bảng (lưới) giúp cho việc quan sát dữ liệu được chi tiết, rõ ràng hơn. Và trong thực tế các dữ liệu của chúng ta cũng thường có nhiều thuộc tính để hiển thị, do đó QTableWidget là một trong các Widget quan trọng thường dùng để hiển thị dữ liệu.
Bài học này Tui sẽ trình bày cách thức kéo thả QTableWidget, tạo các cột, dòng dữ liệu bằng Qt Designer để các bạn có cảm giác trước, các bài học sau Tui sẽ trình bày các kỹ thuật nâng cao về TableWidget chẳng hạn như cách nạp dữ liệu runtime, kết hợp mô hình hướng đối tượng, xử lý MVC Model cho QTable Widget, tương tác dữ liệu với SQLite….
Trước tiên chúng ta cần biết sơ qua Các thuộc tính, phương thức và signal thường dùng của QTableWidget:
Thuộc tính, phương thức, signal | Ý nghĩa chức năng |
---|---|
QTableWidget() | Constructor để tạo đối tượng QTableWidget |
QTableWidget(rows, columns) | Constructor để tạo đối tượng QTableWidget, mặc định có rows dòng và columns cột |
setRowCount(rows) | Hàm thiết lập số dòng cho QTableWidget |
setColumnCount(columns) | Hàm thiết lập số cột cho QTableWidget |
setHorizontalHeaderLabels(labels) | Hàm thiết lập tiêu đề cột |
setColumnWidth(column, width) | Hàm thiết lập độ rộng của cột |
rowCount() | Hàm trả về số dòng trong QTableWidget |
insertRow(row) | Hàm chèn một item mới vào vị trí row trong QTableWidget |
setItem(row, column, item) | Hàm thiết lập các giá trị cho CELL của Item. |
removeRow(current_row) | Hàm xóa dòng khỏi QTableWidget |
itemSelectionChanged | signal để lắng nghe người sử dụng đang chọn dòng dữ liệu nào trong QTableWidget |
currentRow() | Hàm trả về vị trí của dòng đang lựa chọn trên giao diện |
item(row,column) | Trả về ô giao nhau giữa row và column |
Ví dụ dưới đây Tui sẽ hướng dẫn các bạn cách dùng Qt Designer để kéo thả, thiết kế giao diện cho QTableWidget.
Bước 1: Tạo một dự án “LearnQTableWidget” trong Pycharm
Bước 2: Dùng Qt Designer để thiết kế giao diện cho MainWindow.ui
Kéo thả TableWidget vào MainWindow như hình dưới đây:
Sau đó bổ sung các Columns, Rows, Items cho QTableWidget cũng như các Widget cơ bản như hình dưới:
Các QLineEdit, QPushButton các bạn đã được học rất kỹ ở các bài trước rồi nên Tui không nhắc lại.
Bây giờ chúng ta sẽ cấu hình Cột và Dòng cũng như Items cho QTableWidget:
Chúng ta chỉ cần Double Click chuột vào QTableWidget hoặc bấm chuột phải vào nó rồi chọn “Edit Items”:
Lúc này màn hình Edit Table Widget sẽ hiển thị ra như bên dưới:
- Thẻ “Columns” dùng để định nghĩa tiêu đề cột: Ở đây các bạn gõ Song ID, Song Name, và Singer. Có thể thêm Columns bằng cách nhấn vào biểu tưởng dấu +, Có thể xóa bằng biểu tượng dấu trừ, thay đổi vị trí xuất hiện bằng các mũi tên lên xuống
Tương tự như vậy ta vào thẻ “Rows” để tạo các tiêu đề dòng cho QTableWidget:
- Thẻ “Rows” dùng để định nghĩa tiêu đề dòng: Ở đây các bạn thêm các tiêu đề dòng từ 1 tới 5. Có thể thêm Rows bằng cách nhấn vào biểu tưởng dấu +, Có thể xóa bằng biểu tượng dấu trừ, thay đổi vị trí xuất hiện bằng các mũi tên lên xuống.
Cuối cùng là thẻ “Items” dùng để nhập dữ liệu cho QTableWidget:
Ngoài ra QTableWidget cũng cung cấp chức năng định dạng nâng cao cho cả “Columns”, “Rows” và “Items” bằng cách nhấn vào nút “Properties“:
Tương ứng với mỗi thẻ “Columns”, “Rows” hay “Items” mà QTableWidget sẽ cung cấp các thuộc tính khác nhau trong “Properties”. Tùy vào nhu cầu sử dụng mà các bạn có thể cấu hình chẳng hạn như: Chuỗi hiểu thị, Icon, font chữ, màu nền, màu chữ…
Sau khi kéo thả đầy đủ các Widget như giao diện thiết kế, các bạn tiến hành đặt tên cho chúng để ta lập trình:
Bước 3: Dùng Công cụ Generate Python code tự động cho giao diện cho MainWindow.ui để tạo file mã lệnh Python “MainWindow.py“:
# Form implementation generated from reading ui file 'MainWindow.ui'
#
# Created by: PyQt6 UI code generator 6.5.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(476, 376)
self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.tableWidgetSong = QtWidgets.QTableWidget(parent=self.centralwidget)
self.tableWidgetSong.setGeometry(QtCore.QRect(10, 10, 451, 191))
self.tableWidgetSong.setObjectName("tableWidgetSong")
self.tableWidgetSong.setColumnCount(3)
self.tableWidgetSong.setRowCount(5)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setVerticalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setVerticalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setVerticalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setVerticalHeaderItem(3, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setVerticalHeaderItem(4, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setItem(0, 0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setItem(0, 1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setItem(0, 2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setItem(1, 0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setItem(1, 1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setItem(1, 2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setItem(2, 0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setItem(2, 1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setItem(2, 2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setItem(3, 0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setItem(3, 1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setItem(3, 2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setItem(4, 0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setItem(4, 1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidgetSong.setItem(4, 2, item)
self.label = QtWidgets.QLabel(parent=self.centralwidget)
self.label.setGeometry(QtCore.QRect(20, 220, 71, 16))
self.label.setObjectName("label")
self.lineEditSongID = QtWidgets.QLineEdit(parent=self.centralwidget)
self.lineEditSongID.setGeometry(QtCore.QRect(110, 220, 351, 20))
self.lineEditSongID.setObjectName("lineEditSongID")
self.lineEditSongName = QtWidgets.QLineEdit(parent=self.centralwidget)
self.lineEditSongName.setGeometry(QtCore.QRect(110, 250, 351, 20))
self.lineEditSongName.setObjectName("lineEditSongName")
self.label_2 = QtWidgets.QLabel(parent=self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(20, 250, 81, 16))
self.label_2.setObjectName("label_2")
self.label_3 = QtWidgets.QLabel(parent=self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(20, 280, 81, 16))
self.label_3.setObjectName("label_3")
self.lineEditSinger = QtWidgets.QLineEdit(parent=self.centralwidget)
self.lineEditSinger.setGeometry(QtCore.QRect(110, 280, 351, 20))
self.lineEditSinger.setObjectName("lineEditSinger")
self.pushButtonClose = QtWidgets.QPushButton(parent=self.centralwidget)
self.pushButtonClose.setGeometry(QtCore.QRect(110, 310, 75, 23))
self.pushButtonClose.setObjectName("pushButtonClose")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(parent=MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 476, 22))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(parent=MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.pushButtonClose.clicked.connect(MainWindow.close) # type: ignore
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Trần Duy Thanh-QTableWidget"))
item = self.tableWidgetSong.verticalHeaderItem(0)
item.setText(_translate("MainWindow", "1"))
item = self.tableWidgetSong.verticalHeaderItem(1)
item.setText(_translate("MainWindow", "2"))
item = self.tableWidgetSong.verticalHeaderItem(2)
item.setText(_translate("MainWindow", "3"))
item = self.tableWidgetSong.verticalHeaderItem(3)
item.setText(_translate("MainWindow", "4"))
item = self.tableWidgetSong.verticalHeaderItem(4)
item.setText(_translate("MainWindow", "5"))
item = self.tableWidgetSong.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "Song ID"))
item = self.tableWidgetSong.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "Song Name"))
item = self.tableWidgetSong.horizontalHeaderItem(2)
item.setText(_translate("MainWindow", "Singer"))
__sortingEnabled = self.tableWidgetSong.isSortingEnabled()
self.tableWidgetSong.setSortingEnabled(False)
item = self.tableWidgetSong.item(0, 0)
item.setText(_translate("MainWindow", "S1"))
item = self.tableWidgetSong.item(0, 1)
item.setText(_translate("MainWindow", "Không yêu đừng nói lời cay đắng"))
item = self.tableWidgetSong.item(0, 2)
item.setText(_translate("MainWindow", "Tèo Mộng Mơ"))
item = self.tableWidgetSong.item(1, 0)
item.setText(_translate("MainWindow", "P2"))
item = self.tableWidgetSong.item(1, 1)
item.setText(_translate("MainWindow", "Người ấy và Tui Em phải chọn"))
item = self.tableWidgetSong.item(1, 2)
item.setText(_translate("MainWindow", "Tý Khốn Khổ"))
item = self.tableWidgetSong.item(2, 0)
item.setText(_translate("MainWindow", "P3"))
item = self.tableWidgetSong.item(2, 1)
item.setText(_translate("MainWindow", "Yêu Em mà không dám nói"))
item = self.tableWidgetSong.item(2, 2)
item.setText(_translate("MainWindow", "Bin Nhút Nhát"))
item = self.tableWidgetSong.item(3, 0)
item.setText(_translate("MainWindow", "P4"))
item = self.tableWidgetSong.item(3, 1)
item.setText(_translate("MainWindow", "Đập Vỡ Cây Đàn"))
item = self.tableWidgetSong.item(3, 2)
item.setText(_translate("MainWindow", "Tin Nóng Tánh"))
item = self.tableWidgetSong.item(4, 0)
item.setText(_translate("MainWindow", "P5"))
item = self.tableWidgetSong.item(4, 1)
item.setText(_translate("MainWindow", "Áo Em Chưa Mặc 1 Lần"))
item = self.tableWidgetSong.item(4, 2)
item.setText(_translate("MainWindow", "Tủn Thợ May"))
self.tableWidgetSong.setSortingEnabled(__sortingEnabled)
self.label.setText(_translate("MainWindow", "Song ID:"))
self.label_2.setText(_translate("MainWindow", "Song Name:"))
self.label_3.setText(_translate("MainWindow", "Singer:"))
self.pushButtonClose.setText(_translate("MainWindow", "Close"))
Bước 4: Tạo một lớp kế thừa lớp Generate từ bước 4, đặt tên “MainWindowEx.py“:
from MainWindow import Ui_MainWindow
class MainWindowEx(Ui_MainWindow):
def __init__(self):
super().__init__()
def setupUi(self, MainWindow):
super().setupUi(MainWindow)
self.MainWindow=MainWindow
self.tableWidgetSong.itemSelectionChanged.connect(self.processSelectedItem)
def processSelectedItem(self):
row=self.tableWidgetSong.currentRow()
songId=self.tableWidgetSong.item(row,0)
songName=self.tableWidgetSong.item(row,1)
singer=self.tableWidgetSong.item(row,2)
self.lineEditSongID.setText(songId.text())
self.lineEditSongName.setText(songName.text())
self.lineEditSinger.setText(singer.text())
def show(self):
self.MainWindow.show()
Mã lệnh trong “MainWindowEx” Tui có lập trình gọi signal itemSelectionChanged để xử lý dòng dữ liệu mà người dùng chọn trên QTableWidget. Tui tạo slot processSelectedItem tương ứng để xử lý cho signal này. Slot này sẽ lấy dữ liệu của các ô trong dòng đang chọn của QTableWidget và hiển thị lên các QLineEdit.
Bước 5: Tạo “MyApp.py” để thực thi chương trình:
from PyQt6.QtWidgets import QApplication, QMainWindow
from MainWindowEx import MainWindowEx
app=QApplication([])
myWindow=MainWindowEx()
myWindow.setupUi(QMainWindow())
myWindow.show()
app.exec()
Chạy “MyApp.py” ta có kết quả:
Các bạn thấy giao diện của chương trình xuất hiện như trên, các bạn chọn dòng nào thì chi tiết dữ liệu của dòng đó sẽ hiển thị vào QLineEdit ở bên dưới.
Coding đây đủ của bài này các bạn tải ở đây:
https://www.mediafire.com/file/lc84wnz3ikq7mhy/LearnQTableWidget.rar/file
Như vậy là tới đây các bạn đã biết cách sử dụng QTableWidget bằng cách kéo thả vào giao diện, biết cách tạo các Columns, Rows và Item cho QTableWidget. Đồng thời cũng biết cách cấu hình các thuộc tính nâng cao trong nhóm “Properties”. Và cũng biết sử dụng signal itemSelectionChanged để xử lý sự kiện người dùng lựa chọn các dòng trong giao diện QTableWidget.
Bài học sau Tui sẽ tiếp tục hướng dẫn các bạn cách sử dụng và lập trình QTableWidget kéo thả nhưng ở mức nâng cao hơn. Đó là các dữ liệu sẽ được thêm vào QTableWidget lúc Run time, cũng như hướng dẫn các bạn cách xử lý Sửa, Xóa các dòng dữ liệu trong QTableWidget bằng mã lệnh.
Chúc các bạn thành công.
One thought on “Bài 22: Hiển thị dữ liệu dạng bảng- QTableWidget–Part 1”