Bài 15: QRadioButton – Basic Widgets – PyQt6

Trong bài trước chúng ta học về QCheckBox – widget dùng để cung cấp chức năng cho người sử dùng chọn nhiều lựa chọn trên giao diện. Trong bài học này Tui sẽ trình bày về QRadioButton, nó khác biệt với QCheckBox, đó là nó dùng để thiết kế giao diện cho phép người dùng tại một thời điểm chỉ chọn một lựa chọn.

QRadioButton cung cấp 2 trạng thái:

  • on(checked)
  • off(unchecked)

Và các QRadioButton cần được nhóm lại thông qua QButtonGroup nếu trên giao diện bạn muốn thiết kế nhiều nhóm, hoặc chúng ta kéo các Widget vào bên trong các QGroupBox khác nhau. Ví dụ như bạn muốn thiết kế 2 nhóm chọn lựa: Giao diện vừa có nhóm Chọn giới tính Nam hay Nữ, vừa có nhóm chọn trình độ học vấn như Đại học hay cao đẳng….

Tương tự như QCheckBox, thì QRadioButton cũng có một số thuộc tính, phương thức, signal thường dùng sau:

Thuộc tính/Phương thức/signalÝ nghĩa/ Chức năng
objectNameTên QRadioButton dùng để truy suất
setChecked(True/False)Hàm thiết lập Checked hoặc Unchecked cho QRadioButton
isChecked()Hàm trả về trạng thái của QRadioButton có được checked hay không
text()Hàm trả về chuỗi hiển thị trên QRadioButton
toggledSignal để kiểm tra trạng thái của QRadioButton có được checked hay không
clickedSignal để lấy trạng thái true khi người dùng click chọn QRadioButton

Để sử dụng QRadioButton ta có thể thiết kế bằng Qt Designer hoặc làm tuần tự các bước sau, dưới này Tui minh họa bài thay đổi màu nền của Cửa sổ khi người sử dụng nhấn vào các QRadioButton tương ứng:

Bước 1: Import QRadioButton từ module PyQt6.QtWidgets và các thư viện liên quan khác:

from PyQt6.QtWidgets import QApplication
from PyQt6.QtWidgets import QWidget
from PyQt6.QtWidgets import QRadioButton
from PyQt6.QtWidgets import QButtonGroup

Bước 2: Khai báo các đối tượng Widget, QRadioButton, ButtonGroup để tạo các nhóm:

from PyQt6.QtWidgets import QApplication
from PyQt6.QtWidgets import QWidget
from PyQt6.QtWidgets import QRadioButton
from PyQt6.QtWidgets import QButtonGroup

app = QApplication([])

w = QWidget()
w.setWindowTitle("Trần Duy Thanh - QRadioButton")
w.resize(300, 150)

radRed = QRadioButton("Red",w)
radRed.move(20, 20)

radGreen = QRadioButton("Green",w)
radGreen.move(20, 40)

radBlue = QRadioButton("Blue",w)
radBlue.move(20, 60)

color_group = QButtonGroup(w)
color_group.addButton(radRed)
color_group.addButton(radGreen)
color_group.addButton(radBlue)

w.show()

app.exec()

Chạy mã lệnh ở trên ta được giao diện như mong muốn.

Bước 3: Gán Signal cho 3 QRadioButton để đổi màu nền cửa sổ:

def changeBackgroundToRed(value):
    if value==True:
        w.setStyleSheet("background-color:red;");
def changeBackgroundToGreen(value):
    if value == True:
        w.setStyleSheet("background-color:green;")
def changeBackgroundToBlue(value):
    if value == True:
        w.setStyleSheet("background-color:blue;")
radRed.clicked.connect(changeBackgroundToRed)
radGreen.clicked.connect(changeBackgroundToGreen)
radBlue.clicked.connect(changeBackgroundToBlue)

Dưới đây là mã lệnh đầy đủ cho bài đổi màu nền:

from PyQt6.QtWidgets import QApplication
from PyQt6.QtWidgets import QWidget
from PyQt6.QtWidgets import QRadioButton
from PyQt6.QtWidgets import QButtonGroup

app = QApplication([])

w = QWidget()
w.setWindowTitle("Trần Duy Thanh - QRadioButton")
w.resize(300, 150)

radRed = QRadioButton("Red",w)
radRed.move(20, 20)

radGreen = QRadioButton("Green",w)
radGreen.move(20, 40)

radBlue = QRadioButton("Blue",w)
radBlue.move(20, 60)

color_group = QButtonGroup(w)
color_group.addButton(radRed)
color_group.addButton(radGreen)
color_group.addButton(radBlue)

def changeBackgroundToRed(value):
    if value==True:
        w.setStyleSheet("background-color:red;");
def changeBackgroundToGreen(value):
    if value == True:
        w.setStyleSheet("background-color:green;")
def changeBackgroundToBlue(value):
    if value == True:
        w.setStyleSheet("background-color:blue;")
radRed.clicked.connect(changeBackgroundToRed)
radGreen.clicked.connect(changeBackgroundToGreen)
radBlue.clicked.connect(changeBackgroundToBlue)

w.show()

app.exec()

Chạy phần mềm lên và lựa chọn các Màu ta có:

Tiếp theo ta ứng dụng QRadioButton để thiết kế màn hình nhập Personal Information với nhiều thông tin hơn, và đặc biệt ta dùng Qt Designer, GroupBox để group các QRadioButton trên các nhóm khác nhau:

Trong Pycharm ta tạo một dự án tên “LearnQRadioButton“:


Ta dùng Qt Designer để thiết kế giao diện, đặt tên “MainWindow.ui”:

Trước tiên ta kéo các “Group Box” ra giao diện như hình trên, đặt tiêu tiêu, căn lề tiêu đề cũng như chỉnh styleSheet đổi màu nền cho các Group Box.

Ở trên các bạn thấy Tui có tạo 2 Group Box có nền màu vàng (Personal Information) và Group có nền xanh (Other Information). Sau đó trong mỗi Group Box được kéo vào một số Widget như QLabel, QLineEdit, QRadioButton.

Các Group Box, bạn có thể định dạng như hình dưới đây:

  • Thuộc tính title: Để nhập tiêu đề cho Group Box
  • Thuộc tính alignment: Dùng để căn lề cho tiêu đề Group Box
  • Thuộc tính styleSheet: Dùng để định dạng CSS cho GroupBox ví dụ như đường viên, màu viền, màu nền….

Các QRadioButton nào được kéo vào GroupBox nào thì nó sẽ thuộc nhóm đó, tức là khi ta nhấn chọn Radio Button nào thì trong nhóm đó sẽ ảnh hưởng thôi, không liên quan tới GroupBox khác.

Các QRadioButton cũng có nhiều thuộc tính, trong đó các thuộc tính thường dùng như text, icon, checked:

QRadioButton nào muốn mặc định checked thì bạn tick vào thuộc tính checked như hình.

Cuối cùng bạn đặt tên các Widget như hình dưới đây để hỗ trợ cho việc viết mã lệnh tương tác được tốt nhất:

Sau khi đặt xong tên các Widget, các bạn lưu giao diện lại với file “MainWindow.ui” vào đúng dự án trong Pycharm “LearnQRadioButton

Sau đó dùng chức năng Generate Python code đã học để tạo mã lệnh Python cho “MainWindow.ui”, file mã lệnh tự động tạo ra sẽ là “MainWindow.py“:

Mã lệnh của file này như sau:

# 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(449, 378)
        font = QtGui.QFont()
        font.setPointSize(12)
        MainWindow.setFont(font)
        self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.groupBox = QtWidgets.QGroupBox(parent=self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(20, 10, 411, 121))
        self.groupBox.setStyleSheet("border-color: rgb(0, 0, 255);\n"
"background-color: rgb(251, 255, 171);\n"
"")
        self.groupBox.setObjectName("groupBox")
        self.radWoman = QtWidgets.QRadioButton(parent=self.groupBox)
        self.radWoman.setGeometry(QtCore.QRect(110, 90, 91, 18))
        self.radWoman.setChecked(True)
        self.radWoman.setObjectName("radWoman")
        self.radMan = QtWidgets.QRadioButton(parent=self.groupBox)
        self.radMan.setGeometry(QtCore.QRect(220, 90, 83, 18))
        self.radMan.setObjectName("radMan")
        self.lineEditFullName = QtWidgets.QLineEdit(parent=self.groupBox)
        self.lineEditFullName.setGeometry(QtCore.QRect(110, 30, 281, 20))
        self.lineEditFullName.setObjectName("lineEditFullName")
        self.label = QtWidgets.QLabel(parent=self.groupBox)
        self.label.setGeometry(QtCore.QRect(20, 30, 81, 21))
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(parent=self.groupBox)
        self.label_2.setGeometry(QtCore.QRect(20, 90, 71, 21))
        self.label_2.setObjectName("label_2")
        self.lineEditEmail = QtWidgets.QLineEdit(parent=self.groupBox)
        self.lineEditEmail.setGeometry(QtCore.QRect(110, 60, 281, 20))
        self.lineEditEmail.setObjectName("lineEditEmail")
        self.label_3 = QtWidgets.QLabel(parent=self.groupBox)
        self.label_3.setGeometry(QtCore.QRect(20, 60, 81, 21))
        self.label_3.setObjectName("label_3")
        self.groupBox_2 = QtWidgets.QGroupBox(parent=self.centralwidget)
        self.groupBox_2.setGeometry(QtCore.QRect(20, 150, 411, 131))
        self.groupBox_2.setStyleSheet("background-color: rgb(232, 255, 225);")
        self.groupBox_2.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
        self.groupBox_2.setObjectName("groupBox_2")
        self.radBachelor = QtWidgets.QRadioButton(parent=self.groupBox_2)
        self.radBachelor.setGeometry(QtCore.QRect(110, 60, 91, 18))
        self.radBachelor.setObjectName("radBachelor")
        self.radMaster = QtWidgets.QRadioButton(parent=self.groupBox_2)
        self.radMaster.setGeometry(QtCore.QRect(110, 80, 83, 18))
        self.radMaster.setObjectName("radMaster")
        self.lineEditAddress = QtWidgets.QLineEdit(parent=self.groupBox_2)
        self.lineEditAddress.setGeometry(QtCore.QRect(110, 30, 281, 20))
        self.lineEditAddress.setObjectName("lineEditAddress")
        self.label_4 = QtWidgets.QLabel(parent=self.groupBox_2)
        self.label_4.setGeometry(QtCore.QRect(20, 30, 81, 21))
        self.label_4.setObjectName("label_4")
        self.label_5 = QtWidgets.QLabel(parent=self.groupBox_2)
        self.label_5.setGeometry(QtCore.QRect(20, 60, 71, 21))
        self.label_5.setObjectName("label_5")
        self.radDoctoral = QtWidgets.QRadioButton(parent=self.groupBox_2)
        self.radDoctoral.setGeometry(QtCore.QRect(110, 100, 83, 18))
        self.radDoctoral.setChecked(True)
        self.radDoctoral.setObjectName("radDoctoral")
        self.pushButtonSendData = QtWidgets.QPushButton(parent=self.centralwidget)
        self.pushButtonSendData.setGeometry(QtCore.QRect(150, 290, 121, 31))
        self.pushButtonSendData.setObjectName("pushButtonSendData")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(parent=MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 449, 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)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Trần Duy Thanh"))
        self.groupBox.setTitle(_translate("MainWindow", "Personal Information:"))
        self.radWoman.setText(_translate("MainWindow", "Woman"))
        self.radMan.setText(_translate("MainWindow", "Man"))
        self.lineEditFullName.setText(_translate("MainWindow", "Trần Phạm Thanh Trà"))
        self.label.setText(_translate("MainWindow", "Full Name:"))
        self.label_2.setText(_translate("MainWindow", "Gender:"))
        self.lineEditEmail.setText(_translate("MainWindow", "trachanh@gmail.com"))
        self.label_3.setText(_translate("MainWindow", "Email:"))
        self.groupBox_2.setTitle(_translate("MainWindow", "Other Information:"))
        self.radBachelor.setText(_translate("MainWindow", "Bachelor"))
        self.radMaster.setText(_translate("MainWindow", "Master"))
        self.lineEditAddress.setText(_translate("MainWindow", "The Earth"))
        self.label_4.setText(_translate("MainWindow", "Address:"))
        self.label_5.setText(_translate("MainWindow", "Education:"))
        self.radDoctoral.setText(_translate("MainWindow", "Doctoral"))
        self.pushButtonSendData.setText(_translate("MainWindow", "Send Data"))

Tiếp tục tạo một file “MainWindowEX.py” (lớp) kế thừa từ lớp được Generate Python Code trong “MyWindow.py”, mã lệnh tạm thời của “MainWindowEX.py” bạn gõ như dưới đây:

from MainWindow import Ui_MainWindow

class MainWindowEX(Ui_MainWindow):
    def __init__(self):
        pass
    def setupUi(self, MainWindow):
        super().setupUi(MainWindow)
        self.MainWindow=MainWindow
    def show(self):
        self.MainWindow.show()

Các mã lệnh liên quan tới signal cho các Widget ta sẽ xử lý sau.

Tiếp theo, ta tạo thêm “MyApp.py” có mã lệnh dưới đây để khởi tạo chạy 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 chương trình “MyApp.py” lên ta có kết quả:

Khi bạn chạy được giao diện như hình trên là đã thành công.

Bây giờ ta tiếp tục bổ sung một số mã lệnh cho “MainWindowEx.py” để xử lý các Signal:

  • Khi nhấn nút “Send Data” chương trình sẽ lấy các dữ liệu trên giao diện mà người dùng lựa chọn rồi dùng QMessageBox hiển thị các dữ liệu này lên.
import json

from PyQt6.QtWidgets import QMessageBox

from MainWindow import Ui_MainWindow

class MainWindowEX(Ui_MainWindow):
    def __init__(self):
        pass
    def setupUi(self, MainWindow):
        super().setupUi(MainWindow)
        self.MainWindow=MainWindow
        self.pushButtonSendData.clicked.connect(self.getInformation)
    def getInformation(self):
        fullName=self.lineEditFullName.text()
        email=self.lineEditEmail.text()
        gender="Woman"
        if not self.radWoman.isChecked():
            gender=self.radMan.text()
        address=self.lineEditAddress.text()
        degree="Bachelor"
        if self.radMaster.isChecked():
            degree=self.radMaster.text()
        elif self.radDoctoral.isChecked():
            degree=self.radDoctoral.text()
        information={"FullName":fullName,
                     "Email":email,
                     "Gender":gender,
                     "Address":address,
                     "Degree":degree
                     }
        self.msgBox=QMessageBox()
        self.msgBox.setWindowTitle("Information")
        self.msgBox.setText(json.dumps(information, ensure_ascii=False))
        self.msgBox.show()
    def show(self):
        self.MainWindow.show()

Mã lệnh ở trên, Tui chủ ý đưa dữ liệu về dạng JSON để các bạn làm quen ở các bài học trong tương lai, vì JSON là một trong các cấu trúc lưu trữ dữ liệu phổ biến nhất hiện nay.

Sau khi bổ sung xong mã lệnh cho “MainWindowEx.py”, bây giờ các bạn chạy lại “MyApp.py”, khi bấm “Send Data” ta sẽ có kết quả:

Như vậy tới đây Tui đã trình bày xong về lý thuyết cũng như cách kỹ thuật lập trình với QRadioButton. Các bạn đã biết được ý nghĩa của các thuộc tính, cách gán signal, và đã sử dụng được 2 cách xử lý sự kiện trên QRadioButton:

  • Xử lý sự kiện QRadioButton ngay lúc người dùng thay đổi lựa chọn trên các widget này
  • Xử lý sự kiện QRadioButton sau khi người dùng nhấn vào nút Send Data

Việc biết được các kiến thức và kỹ thuật xử lý này sẽ giúp ích cho các bạn trong cách vận dụng QRadioButton vào từng trường hợp cụ thể. Các bạn chú ý đọc kỹ và thực hành lại nhiều lần để hiểu rõ hơn về Widget này.

Mã lệnh của bài học QRadioButton các bạn có thể tải ở đây:

https://www.mediafire.com/file/fntsllw6njwapak/LearnQRadioButton.rar/file

Bài học sau Tui sẽ trình bày về cách sử dụng QComboBox QListWidget để hiển thị dữ liệu dạng danh sách, đây là một các Widget rất quan trọng để hỗ trợ việc hiển thị danh sách dữ liệu, cho phép người dùng chọn 1 phần tử hay chọn nhiều phần từ… Các bạn chú ý theo dõi.

Chúc các bạn thành công.

Leave a Reply