Chuyển đến nội dung chính

Hướng dẫn PySide6: Xây dựng ứng dụng GUI với Python

Tìm hiểu những điều cơ bản về PySide6 để xây dựng ứng dụng máy tính để bàn đầu tiên và tích hợp trực quan hóa dữ liệu từ các thư viện khoa học dữ liệu phổ biến vào đó.
· 14 phút đọc

Khám phá cùng AI

Hãy đối diện sự thật: các bên liên quan không chuyên môn hoặc người dùng cuối không hứng thú với Jupyter Notebook hay các script Python mà bạn tạo ra với tư cách là người làm dữ liệu. Họ muốn có thể tương tác với giải pháp và tự mình xem kết quả.

Đó là lý do chúng ta cần biến công việc của mình thành báo cáo phân tích, bảng điều khiển, hoặc ứng dụng khoa học dữ liệu. Trong khi báo cáo, bảng điều khiển và ứng dụng web khá phổ biến, một lựa chọn ít được khám phá hơn là ứng dụng máy tính để bàn.

Hãy tưởng tượng bạn có thể thiết kế một ứng dụng nơi người dùng bấm nút, điền biểu mẫu và điều hướng qua các menu — tất cả qua một giao diện rõ ràng, dễ chịu ngay trên máy tính của bạn. Nghe tuyệt chứ?

Trong hướng dẫn này, chúng tôi sẽ giới thiệu PySide6, hỗ trợ bạn cài đặt ban đầu và xây dựng ứng dụng máy tính để bàn đầu tiên. Chúng tôi cũng sẽ khám phá các widget thường dùng, tích hợp trực quan hóa dữ liệu từ các thư viện khoa học dữ liệu phổ biến và chia sẻ tài nguyên hữu ích.

PySide6 là gì?

PySide6 là một bộ công cụ cho phép bạn tạo ứng dụng phần mềm bằng ngôn ngữ lập trình Python với giao diện đồ họa hấp dẫn và trực quan.

Nó giống như bộ khối lắp ghép cho phần mềm, cho phép ngay cả người mới học lập trình cũng có thể ghép nên các thành phần trực quan và tương tác tạo nên một ứng dụng. Với PySide6, bạn có thể biến ý tưởng thành ứng dụng hoạt động thực sự trên Windows, Mac, Linux, và thậm chí cả nền tảng di động.

Thiết lập PySide6

Với phần thiết lập, chúng tôi giả định bạn đã cài Python và có sẵn IDE quen dùng. Việc cài đặt khá đơn giản.

Mở terminal và chạy lệnh sau, vậy là xong.

pip3 install pyside6

Xây dựng ứng dụng PySide6 đầu tiên của bạn

Giờ bạn đã cài thư viện thành công, bước tiếp theo là xây dựng ứng dụng PySide6 đầu tiên. Đây cũng là cách để kiểm tra thiết lập hoạt động ổn, đồng thời cho bạn cảm nhận về ứng dụng máy tính để bàn.

Tạo một tệp Python tên “main.py” và sao chép, dán đoạn mã sau.

import sys
from PySide6.QtWidgets import QApplication, QLabel
app = QApplication(sys.argv)
label = QLabel('Hello, PySide6!')
label.show()
sys.exit(app.exec_())

Chúng ta sẽ hiểu mã trong chốc lát, nhưng trước hết, hãy chạy tệp Python qua terminal như sau:

python3 run main.py

Chúc mừng, bạn đã xây dựng được ứng dụng máy tính để bàn đầu tiên! Bạn sẽ thấy màn hình như sau:

Ứng dụng máy tính để bàn “Hello, PySide6” (Hình của tác giả)

Ứng dụng máy tính để bàn “Hello, PySide6” (Hình của tác giả)

Giờ hãy phân tích đoạn script PySide6 đơn giản ở trên. Trước hết, chúng ta nhập các mô-đun liên quan:

import sys
from PySide6.QtWidgets import QApplication, QLabel
  • sys là mô-đun thư viện chuẩn Python cung cấp quyền truy cập một số biến do trình thông dịch Python dùng hoặc quản lý. Trong ngữ cảnh ứng dụng PySide6, nó thường được dùng cho đối số dòng lệnh. Xem hướng dẫn phân tích đối số dòng lệnh của chúng tôi để tìm hiểu thêm.
  • QApplication và QLabel được nhập từ PySide6.QtWidgets. QApplication là lớp quản lý ứng dụng cốt lõi trong PySide6, cần thiết cho mọi ứng dụng GUI. QLabel là một widget hiển thị văn bản, dùng để hiển thị một thông điệp đơn giản.

Tiếp theo, chúng ta tạo một thể hiện của QApplication.

app = QApplication(sys.argv)

Dòng này là bắt buộc trong mọi ứng dụng PySide6. sys.argv được dùng để truyền đối số dòng lệnh cho ứng dụng. Ngay cả khi bạn không dùng đối số dòng lệnh, sys.argv vẫn cần thiết vì nó khởi tạo QApplication với một số giá trị mặc định.

label = QLabel('Hello, PySide6!')

Tiếp theo, chúng ta tạo một widget QLabel với văn bản "Hello, PySide6!". Đây là văn bản sẽ được hiển thị trong cửa sổ ứng dụng.

label.show()

Dòng này làm cho label hiển thị. Theo mặc định, các widget trong PySide6 sẽ không hiển thị cho đến khi bạn gọi hiển thị một cách tường minh.

sys.exit(app.exec_())

Cuối cùng, dòng này khởi động vòng lặp sự kiện của ứng dụng. Phương thức exec_() của QApplication đưa ứng dụng vào vòng lặp chính, nơi mọi sự kiện (như bấm chuột và gõ phím) được xử lý. Lời gọi sys.exit() đảm bảo thoát sạch khi ứng dụng đóng lại. Vòng lặp sự kiện chạy cho đến khi thể hiện QApplication nhận tín hiệu thoát, chẳng hạn đóng cửa sổ.

Như đã thấy ở phần kết quả trước đó, script của chúng ta tạo một ứng dụng GUI cơ bản với một cửa sổ đơn hiển thị dòng chữ “Hello, PySide6!”.

Tích hợp các widget PySide6 vào ứng dụng GUI

Trong ngữ cảnh PySide6 và GUI, widget là những khối xây dựng cơ bản để tạo giao diện người dùng trong một ứng dụng phần mềm. Hãy coi widget là các thành phần bạn thấy và tương tác trong bất kỳ ứng dụng nào — như nút bấm, ô nhập văn bản, nhãn, thanh trượt và danh sách thả xuống.

Trong ứng dụng PySide6 đầu tiên, chúng ta đã thấy một widget nhãn dùng để hiển thị văn bản. Khi xây dựng GUI với PySide6, về bản chất chúng ta đang sắp xếp các widget này trong một cửa sổ theo cách phù hợp cho ứng dụng. Mỗi widget có một mục đích cụ thể và tương tác với người dùng theo cách khác nhau.

Danh sách đầy đủ các widget và cách dùng có trong tài liệu chính thức, nhưng những widget thường dùng nhất là:

  • QLabel: Widget dùng để hiển thị văn bản hoặc hình ảnh. Thường dùng để hiển thị hướng dẫn, thông điệp, hoặc thậm chí hiển thị hình ảnh trong GUI.
  • QPushButton: Nút có thể bấm để kích hoạt hành động nào đó. Đây là một trong những widget cơ bản nhất trong phát triển GUI, dùng để gửi biểu mẫu, khởi động tiến trình, v.v.
  • QLineEdit: Widget cho phép người dùng nhập và chỉnh sửa một dòng văn bản. Thường dùng trong biểu mẫu và phần cài đặt nơi cần nhập văn bản, như nhập tên hoặc số.
  • QComboBox: Kết hợp giữa danh sách thả xuống và ô văn bản, cho phép người dùng chọn một tùy chọn từ danh sách có sẵn hoặc tự gõ.
  • QCheckBox: Hiển thị một ô có thể chọn hoặc bỏ chọn. Thường dùng để bật/tắt tính năng hoặc thể hiện sự đồng ý với điều khoản.
  • QRadioButton: Dùng để chọn một tùy chọn trong một nhóm; chỉ cho phép một lựa chọn duy nhất, phù hợp với các lựa chọn loại trừ nhau.
  • QTextEdit: Widget chỉnh sửa văn bản nhiều dòng, cung cấp nhiều chức năng hơn QLineEdit, như định dạng văn bản, sao chép dán và cuộn.
  • QSlider: Cung cấp điều khiển dạng thanh trượt, hữu ích để nhập giá trị số trong một khoảng, như chỉnh âm lượng hoặc đặt bộ lọc giá.
  • QSpinBox: Widget cho phép người dùng chọn một số trong một khoảng cho trước. Người dùng có thể tăng/giảm giá trị bằng các mũi tên lên/xuống nhỏ.
  • QProgressBar: Hiển thị tiến độ của một tác vụ. Biểu diễn trực quan phần trăm hoàn thành, hữu ích khi theo dõi tiến trình như tải lên hoặc tải xuống tệp.
  • QTableWidget: Hữu ích để hiển thị dữ liệu theo dạng bảng. Cho phép tổ chức dữ liệu thành hàng và cột, giúp hiển thị và tương tác với dữ liệu có cấu trúc dễ dàng hơn.

Hãy tạo một ứng dụng sử dụng các widget phổ biến này và hiển thị chúng:

import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QLineEdit, QComboBox, QCheckBox, QRadioButton, QTextEdit, QSlider, QSpinBox, QProgressBar, QTableWidget, QTableWidgetItem, QVBoxLayout, QHBoxLayout, QWidget

class DemoWindow(QMainWindow):
   def __init__(self):
       super().__init__()

       # Main Widget and Layout
       main_widget = QWidget()
       self.setCentralWidget(main_widget)
       main_layout = QVBoxLayout(main_widget)

       # Function to add widget with label
       def add_widget_with_label(layout, widget, label_text):
           hbox = QHBoxLayout()
           label = QLabel(label_text)
           hbox.addWidget(label)
           hbox.addWidget(widget)
           layout.addLayout(hbox)

       # QLabel
       self.label = QLabel('Hello PySide6!')
       add_widget_with_label(main_layout, self.label, 'QLabel:')

       # QPushButton
       self.button = QPushButton('Click Me')
       self.button.clicked.connect(self.on_button_clicked)
       add_widget_with_label(main_layout, self.button, 'QPushButton:')

       # QLineEdit
       self.line_edit = QLineEdit()
       add_widget_with_label(main_layout, self.line_edit, 'QLineEdit:')

       # QComboBox
       self.combo_box = QComboBox()
       self.combo_box.addItems(['Option 1', 'Option 2', 'Option 3'])
       add_widget_with_label(main_layout, self.combo_box, 'QComboBox:')

       # QCheckBox
       self.check_box = QCheckBox('Check Me')
       add_widget_with_label(main_layout, self.check_box, 'QCheckBox:')

       # QRadioButton
       self.radio_button = QRadioButton('Radio Button')
       add_widget_with_label(main_layout, self.radio_button, 'QRadioButton:')

       # QTextEdit
       self.text_edit = QTextEdit()
       add_widget_with_label(main_layout, self.text_edit, 'QTextEdit:')

       # QSlider
       self.slider = QSlider()
       add_widget_with_label(main_layout, self.slider, 'QSlider:')

       # QSpinBox
       self.spin_box = QSpinBox()
       add_widget_with_label(main_layout, self.spin_box, 'QSpinBox:')

       # QProgressBar
       self.progress_bar = QProgressBar()
       add_widget_with_label(main_layout, self.progress_bar, 'QProgressBar:')

       # QTableWidget
       self.table_widget = QTableWidget(5, 3) 
       for i in range(5):
           for j in range(3):
               item = QTableWidgetItem(f"Cell {i+1},{j+1}")
               self.table_widget.setItem(i, j, item)
       add_widget_with_label(main_layout, self.table_widget, 'QTableWidget:')

   def on_button_clicked(self):
       self.label.setText('Button Clicked!')

# Run the application
app = QApplication(sys.argv)
window = DemoWindow()
window.show()
sys.exit(app.exec_())

Kết quả như sau:

Ứng dụng máy tính để bàn với các widget (Hình của tác giả)

Ứng dụng máy tính để bàn với các widget (Hình của tác giả)

Chúng ta đã tạo thành công một ứng dụng máy tính để bàn tích hợp các widget phổ biến nhất. Để dễ hiểu, chúng tôi đã thêm nhãn bên cạnh mỗi widget. Dù đây chỉ là ứng dụng mẫu, giờ chúng ta có thể chọn và dùng một trong các widget phổ biến này cho những ứng dụng phức tạp hơn.

Ứng dụng trực quan hóa dữ liệu với PySide6, Matplotlib và Seaborn

Để tạo ứng dụng này, trước tiên chúng ta sẽ chọn một bộ dữ liệu phổ biến và tạo các biểu đồ độc lập. Bước này giống với phân tích dữ liệu khám phá hàng ngày trong công việc khoa học dữ liệu. Sau đó, chúng ta sẽ đóng gói các biểu đồ này vào một ứng dụng máy tính để bàn, giống như cách biến báo cáo và phân tích thành ứng dụng tương tác.

Trước khi bắt đầu, hãy đảm bảo chúng ta có đầy đủ thư viện cần thiết bằng cách chạy lệnh sau trong terminal.

pip3 install matplotlib seaborn

Bước 1: Tạo các biểu đồ độc lập đơn giản

Ở đây, chúng ta tải “bộ dữ liệu iris” nổi tiếng có sẵn trong gói trực quan hóa Python — Seaborn. Chúng ta dùng chính gói này cùng với Matplotlib để tạo biểu đồ. Để hiểu toàn diện về vẽ biểu đồ với Seaborn, bạn có thể xem hướng dẫn trực quan hóa Python Seaborn của chúng tôi.

import seaborn as sns
import matplotlib.pyplot as plt
# Load the Iris dataset
iris = sns.load_dataset("iris")

Tiếp đó, chúng ta tạo các biểu đồ như sau:

plt.figure(figsize=(6, 4))
sns.scatterplot(data=iris, x="sepal_length", y="sepal_width", hue="species")
plt.title("Sepal Length vs Sepal Width")
plt.show()

Biểu đồ đầu tiên là biểu đồ phân tán (scatter) giữa chiều dài đài hoa và chiều rộng đài hoa, tô màu theo loài.

Biểu đồ #1: Chiều dài đài hoa so với chiều rộng đài hoa (Hình của tác giả)

Biểu đồ #1: Chiều dài đài hoa so với chiều rộng đài hoa (Hình của tác giả)

Biểu đồ thứ hai là biểu đồ histogram của chiều dài cánh hoa, tô màu theo loài.

plt.figure(figsize=(6, 4))
sns.histplot(iris, x="petal_length", hue="species", kde=True)
plt.title("Histogram of Petal Length")
plt.show()

Và chúng ta thấy kết quả như sau:

Biểu đồ #2: Histogram chiều dài cánh hoa (Hình của tác giả)

Biểu đồ #2: Histogram chiều dài cánh hoa (Hình của tác giả)

Cuối cùng, hãy vẽ biểu đồ hộp để thể hiện phân phối chiều rộng cánh hoa theo từng loài.

plt.figure(figsize=(6, 4))
sns.boxplot(x="species", y="petal_width", data=iris)
plt.title("Box Plot of Petal Width")
plt.show()

Biểu đồ như sau:

Biểu đồ #3: Box plot chiều rộng cánh hoa (Hình của tác giả)

Các biểu đồ này cung cấp những góc nhìn khác nhau về bộ dữ liệu Iris, cho thấy mối quan hệ và phân phối của các đặc trưng theo từng loài hoa.

Bước 2: Tích hợp các biểu đồ vào ứng dụng máy tính để bàn

Trước hết, hãy xem mã và cùng tìm hiểu.

import sys
import seaborn as sns
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure

class IrisVisualizer(QMainWindow):
   def __init__(self):
       super().__init__()
       self.setWindowTitle("Iris Dataset Visualizations")
       self.setGeometry(100, 100, 1200, 900)  # x, y, width, height
       self.initUI()

   def initUI(self):
       central_widget = QWidget(self)
       self.setCentralWidget(central_widget)
       layout = QVBoxLayout(central_widget)

       # Adding multiple plots
       self.addScatterPlot(layout)
       self.addHistogram(layout)
       self.addBoxPlot(layout)

   def addPlotCanvas(self, layout, plot_func):
       canvas = FigureCanvas(Figure(figsize=(6, 4)))
       plot_func(canvas.figure)
       layout.addWidget(canvas)

   def addScatterPlot(self, layout):
       def scatter_plot(figure):
           iris = sns.load_dataset("iris")
           ax = figure.add_subplot(111)
           sns.scatterplot(data=iris, x="sepal_length", y="sepal_width", hue="species", ax=ax)
           ax.set_title("Sepal Length vs Sepal Width")

       self.addPlotCanvas(layout, scatter_plot)

   def addHistogram(self, layout):
       def histogram(figure):
           iris = sns.load_dataset("iris")
           ax = figure.add_subplot(111)
           sns.histplot(iris, x="petal_length", hue="species", kde=True, ax=ax)
           ax.set_title("Histogram of Petal Length")

       self.addPlotCanvas(layout, histogram)

   def addBoxPlot(self, layout):
       def box_plot(figure):
           iris = sns.load_dataset("iris")
           ax = figure.add_subplot(111)
           sns.boxplot(x="species", y="petal_width", data=iris, ax=ax)
           ax.set_title("Box Plot of Petal Width")

       self.addPlotCanvas(layout, box_plot)

# Run the application
app = QApplication(sys.argv)
window = IrisVisualizer()
window.show()
sys.exit(app.exec_())

Chúng ta cấu trúc ứng dụng xoay quanh lớp IrisVisualizer, kế thừa QMainWindow của PySide6. Lớp này thiết lập cửa sổ chính và bố cục của nó, đóng vai trò là vùng chứa cho các biểu đồ. Mỗi biểu đồ được nhúng vào GUI bằng FigureCanvasQTAgg từ Matplotlib, cho phép hiển thị các figure của Matplotlib như widget PySide6.

Mấu chốt của việc tích hợp nằm ở phương thức addPlotCanvas. Phương thức này tạo một figure Matplotlib, vẽ biểu đồ lên đó, rồi nhúng figure này vào bố cục của ứng dụng. Các phương thức cụ thể như addScatterPlot, addHistogram và addBoxPlot định nghĩa từng biểu đồ riêng lẻ — vốn là các biểu đồ độc lập ở bước trước. Bố cục cửa sổ chính được đặt là bố cục hộp dọc (QVBoxLayout), xếp chồng tất cả biểu đồ theo chiều dọc.

Hãy xem ứng dụng cuối cùng của chúng ta:

Ứng dụng trực quan hóa bộ dữ liệu Iris trên máy tính để bàn (Hình của tác giả)

Ứng dụng trực quan hóa bộ dữ liệu Iris trên máy tính để bàn (Hình của tác giả)

Chẳng phải ứng dụng này tốt hơn một biểu đồ trong Jupyter Notebook sao? Dĩ nhiên đây là ví dụ đơn giản, nhưng khi đã nắm các khái niệm đằng sau việc tạo ứng dụng, chúng ta có thể nâng cấp thành bảng điều khiển thông tin dữ liệu hoàn chỉnh hoặc một ứng dụng khoa học dữ liệu.

Kết luận

Hướng dẫn này đã giới thiệu PySide6, một thư viện Python cho phép người làm dữ liệu tạo ứng dụng máy tính để bàn có GUI bằng ngôn ngữ quen thuộc nhất — Python. Chúng ta bắt đầu từ việc cài đặt PySide6 và tạo ứng dụng desktop đầu tiên.

Sau đó, chúng ta mở rộng để bao quát các widget thường dùng nhất trong ứng dụng desktop.

Cuối cùng, chúng ta hiểu cách tích hợp trực quan hóa từ các thư viện phổ biến như Seaborn và Matplotlib trực tiếp vào ứng dụng PySide6.

Để học thêm, chúng tôi khuyến khích bạn tham khảo tài liệu chính thức và theo đuổi sự tò mò của mình để tạo bất kỳ ứng dụng yêu thích nào. Ngoài ra, bạn cũng có thể xem hướng dẫn của chúng tôi về tạo ứng dụng desktop GUI trong Python nhưng dùng thư viện thay thế là Tkinter.

Arunn Thevapalan

Tác giả

Arunn Thevapalan

Với vai trò nhà khoa học dữ liệu cao cấp, tôi thiết kế, phát triển và triển khai các giải pháp học máy quy mô lớn để giúp doanh nghiệp ra quyết định dựa trên dữ liệu hiệu quả hơn. Với vai trò tác giả về khoa học dữ liệu, tôi chia sẻ những bài học kinh nghiệm, lời khuyên nghề nghiệp và các hướng dẫn thực hành chuyên sâu.

Chủ đề

Liên quan