Nếu như bạn đã quá quen thuộc với nhưng công nghệ làm ứng dụng Desktop kinh điển như Winform, WPF (C#) hay Swing, JavaFx (Java) và nghĩ rằng Python chỉ để làm các ứng dụng không có đồ họa như AI hay Data science, Console terminal … thì bạn chưa thật hiểu được sức mạnh bên trong của Python. Trong bài viết này tôi sẽ cùng các bạn xây dựng một ứng dụng Desktop dựa trên Python và các phần mềm hỗ trợ tạo GUI (giao diện người dùng) khá xịn xò không kém những công nghệ của C# hay Java nhé.

Chúng ta sẽ sử dụng PyQt5 – một thư viện cho phép bạn sử dụng Qt GUI.

Chúng ta sẽ cùng đi tìm hiểu qua các bước:

1. Tìm hiểu, cách cài đặt PyQt5 và công cụ Qt Designer

2. Thực hành ngay với ví dụ “Lập trình socket”

2.1. Xây dựng giao diện bằng Qt Designer

2.2. Xây dựng Back-end.

Và giờ là lúc bắt tay vào làm thôi: 

1. Cài đặt PyQt5 và công cụ Qt Designer

a) Cài đặt PyQt5:
PyQt là một thư viện cho phép bạn sử dụng Qt GUI, một framework rất nổi tiếng của C++. PyQt có nhiều phiên bản nhưng gần đây nhất và được hỗ trợ nhiều nhất là PyQt5. Để cài đặt thư viện này, chúng ta cài đặt bằng dòng lệnh kinh điển như sau:
  • Mở console bằng cách Run (windows+ R) –> cmd –> Enter
  • Trong màn hình cmd: gõ dòng lệnh sau
python -m pip install PyQt5 
# pip install PyQt5

Vậy là đã cài đặt xong thư viện PyQt5.

Đơn giản vậy thôi.

b) Cài đặt QtDesigner

Các bạn có thể tải về và cài đặt tại đây: Download QtDesigner

Sau khi cài đặt xong, mở Qt Designer lên chiêm ngưỡng như sau:

Vậy là đã đủ đồ nghề để bắt đầu xây dựng chương trình rồi nhé. Bắt tay vào xây dựng giao diện và code nào.

2. Thực hành “Lập trình socket với Python”

2.1 Xây dựng giao diện bằng Qt Designer

B1. Mở Qt Designer lên và chọn mặc định Main Windows –> Create

B2: Nếu bạn đã từng làm quen lập trình với Winform sẽ khá quen thuộc với giao diện này. Gồm 03 phần chính: bên trái là các Widget, ở giữa là giao diện xem trước và bên phải là tùy chỉnh các thuộc tính Property. Các bạn chỉ việc kéo thả các đối tượng cần sử dụng vào form theo ý muốn chủ quan và chỉnh sửa các thuộc tính ở Property bên phải.

Với yêu cầu bài toán đặt ra, chúng ta tạm thời tạo giao diện chương trình như sau:

Cuối cùng là Ctrl + R để xem lại giao diện nhé:

Bước cuối cùng để tạo giao diện là chuyển giao diện này sang code PyQt5. Các bạn lưu file .ui này vào ProjectFolder của mình nhé

Sau đó các bạn chạy lệnh sau:

#vidu: python -m PyQt5.uic.pyuic clientform.ui -o client.py -x

Đây là full code phần giao diện file client.py mà python đã export tự động từ dòng lệnh phía trên:

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_frmMainClient(object):
    def setupUi(self, frmMainClient):
        frmMainClient.setObjectName("frmMainClient")
        frmMainClient.resize(450, 278)
        frmMainClient.setMaximumSize(QtCore.QSize(500, 500))
        self.centralwidget = QtWidgets.QWidget(frmMainClient)
        self.centralwidget.setObjectName("centralwidget")
        self.cmd_Connect = QtWidgets.QPushButton(self.centralwidget)
        self.cmd_Connect.setGeometry(QtCore.QRect(350, 20, 71, 31))
        self.cmd_Connect.setObjectName("cmd_Connect")
        self.txt_IP = QtWidgets.QLineEdit(self.centralwidget)
        self.txt_IP.setGeometry(QtCore.QRect(120, 20, 221, 31))
        self.txt_IP.setObjectName("txt_IP")
        self.cmd_ProcessRunning = QtWidgets.QPushButton(self.centralwidget)
        self.cmd_ProcessRunning.setGeometry(QtCore.QRect(40, 80, 71, 141))
        self.cmd_ProcessRunning.setObjectName("cmd_ProcessRunning")
        self.cmd_AppRunning = QtWidgets.QPushButton(self.centralwidget)
        self.cmd_AppRunning.setGeometry(QtCore.QRect(120, 80, 221, 41))
        self.cmd_AppRunning.setObjectName("cmd_AppRunning")
        self.cmd_Shutdown = QtWidgets.QPushButton(self.centralwidget)
        self.cmd_Shutdown.setGeometry(QtCore.QRect(120, 130, 101, 41))
        self.cmd_Shutdown.setObjectName("cmd_Shutdown")
        self.cmd_MonitorCapture = QtWidgets.QPushButton(self.centralwidget)
        self.cmd_MonitorCapture.setGeometry(QtCore.QRect(230, 130, 111, 41))
        self.cmd_MonitorCapture.setObjectName("cmd_MonitorCapture")
        self.cmd_keystroke = QtWidgets.QPushButton(self.centralwidget)
        self.cmd_keystroke.setGeometry(QtCore.QRect(350, 80, 71, 141))
        self.cmd_keystroke.setObjectName("cmd_keystroke")
        self.cmd_RegisterEdit = QtWidgets.QPushButton(self.centralwidget)
        self.cmd_RegisterEdit.setGeometry(QtCore.QRect(120, 177, 101, 41))
        self.cmd_RegisterEdit.setObjectName("cmd_RegisterEdit")
        self.cmd_Quit = QtWidgets.QPushButton(self.centralwidget)
        self.cmd_Quit.setGeometry(QtCore.QRect(230, 177, 111, 41))
        self.cmd_Quit.setObjectName("cmd_Quit")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(40, 20, 71, 31))
        self.label.setMinimumSize(QtCore.QSize(55, 16))
        self.label.setMaximumSize(QtCore.QSize(100, 100))
        font = QtGui.QFont()
        font.setPointSize(9)
        font.setBold(False)
        font.setWeight(50)
        self.label.setFont(font)
        self.label.setFrameShadow(QtWidgets.QFrame.Plain)
        self.label.setTextFormat(QtCore.Qt.PlainText)
        self.label.setScaledContents(False)
        self.label.setIndent(9)
        self.label.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
        self.label.setObjectName("label")
        frmMainClient.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(frmMainClient)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 450, 26))
        self.menubar.setObjectName("menubar")
        frmMainClient.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(frmMainClient)
        self.statusbar.setObjectName("statusbar")
        frmMainClient.setStatusBar(self.statusbar)

        self.retranslateUi(frmMainClient)
        QtCore.QMetaObject.connectSlotsByName(frmMainClient)

    def retranslateUi(self, frmMainClient):
        _translate = QtCore.QCoreApplication.translate
        frmMainClient.setWindowTitle(_translate("frmMainClient", "Lập trình socket - Client side"))
        self.cmd_Connect.setText(_translate("frmMainClient", "Kết nối"))
        self.cmd_ProcessRunning.setText(_translate("frmMainClient", "Process \n"
"Running"))
        self.cmd_AppRunning.setText(_translate("frmMainClient", "App Running"))
        self.cmd_Shutdown.setText(_translate("frmMainClient", "Tắt máy"))
        self.cmd_MonitorCapture.setText(_translate("frmMainClient", "Chụp màn hình"))
        self.cmd_keystroke.setText(_translate("frmMainClient", "Keystroke"))
        self.cmd_RegisterEdit.setText(_translate("frmMainClient", "Sửa Registry"))
        self.cmd_Quit.setText(_translate("frmMainClient", "Thoát"))
        self.label.setText(_translate("frmMainClient", "Nhập IP:"))from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_frmMainClient(object):
    def setupUi(self, frmMainClient):
        frmMainClient.setObjectName("frmMainClient")
        frmMainClient.resize(450, 278)
        frmMainClient.setMaximumSize(QtCore.QSize(500, 500))
        self.centralwidget = QtWidgets.QWidget(frmMainClient)
        self.centralwidget.setObjectName("centralwidget")
        self.cmd_Connect = QtWidgets.QPushButton(self.centralwidget)
        self.cmd_Connect.setGeometry(QtCore.QRect(350, 20, 71, 31))
        self.cmd_Connect.setObjectName("cmd_Connect")
        self.txt_IP = QtWidgets.QLineEdit(self.centralwidget)
        self.txt_IP.setGeometry(QtCore.QRect(120, 20, 221, 31))
        self.txt_IP.setObjectName("txt_IP")
        self.cmd_ProcessRunning = QtWidgets.QPushButton(self.centralwidget)
        self.cmd_ProcessRunning.setGeometry(QtCore.QRect(40, 80, 71, 141))
        self.cmd_ProcessRunning.setObjectName("cmd_ProcessRunning")
        self.cmd_AppRunning = QtWidgets.QPushButton(self.centralwidget)
        self.cmd_AppRunning.setGeometry(QtCore.QRect(120, 80, 221, 41))
        self.cmd_AppRunning.setObjectName("cmd_AppRunning")
        self.cmd_Shutdown = QtWidgets.QPushButton(self.centralwidget)
        self.cmd_Shutdown.setGeometry(QtCore.QRect(120, 130, 101, 41))
        self.cmd_Shutdown.setObjectName("cmd_Shutdown")
        self.cmd_MonitorCapture = QtWidgets.QPushButton(self.centralwidget)
        self.cmd_MonitorCapture.setGeometry(QtCore.QRect(230, 130, 111, 41))
        self.cmd_MonitorCapture.setObjectName("cmd_MonitorCapture")
        self.cmd_keystroke = QtWidgets.QPushButton(self.centralwidget)
        self.cmd_keystroke.setGeometry(QtCore.QRect(350, 80, 71, 141))
        self.cmd_keystroke.setObjectName("cmd_keystroke")
        self.cmd_RegisterEdit = QtWidgets.QPushButton(self.centralwidget)
        self.cmd_RegisterEdit.setGeometry(QtCore.QRect(120, 177, 101, 41))
        self.cmd_RegisterEdit.setObjectName("cmd_RegisterEdit")
        self.cmd_Quit = QtWidgets.QPushButton(self.centralwidget)
        self.cmd_Quit.setGeometry(QtCore.QRect(230, 177, 111, 41))
        self.cmd_Quit.setObjectName("cmd_Quit")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(40, 20, 71, 31))
        self.label.setMinimumSize(QtCore.QSize(55, 16))
        self.label.setMaximumSize(QtCore.QSize(100, 100))
        font = QtGui.QFont()
        font.setPointSize(9)
        font.setBold(False)
        font.setWeight(50)
        self.label.setFont(font)
        self.label.setFrameShadow(QtWidgets.QFrame.Plain)
        self.label.setTextFormat(QtCore.Qt.PlainText)
        self.label.setScaledContents(False)
        self.label.setIndent(9)
        self.label.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
        self.label.setObjectName("label")
        frmMainClient.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(frmMainClient)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 450, 26))
        self.menubar.setObjectName("menubar")
        frmMainClient.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(frmMainClient)
        self.statusbar.setObjectName("statusbar")
        frmMainClient.setStatusBar(self.statusbar)

        self.retranslateUi(frmMainClient)
        QtCore.QMetaObject.connectSlotsByName(frmMainClient)

    def retranslateUi(self, frmMainClient):
        _translate = QtCore.QCoreApplication.translate
        frmMainClient.setWindowTitle(_translate("frmMainClient", "Lập trình socket - Client side"))
        self.cmd_Connect.setText(_translate("frmMainClient", "Kết nối"))
        self.cmd_ProcessRunning.setText(_translate("frmMainClient", "Process \n"
"Running"))
        self.cmd_AppRunning.setText(_translate("frmMainClient", "App Running"))
        self.cmd_Shutdown.setText(_translate("frmMainClient", "Tắt máy"))
        self.cmd_MonitorCapture.setText(_translate("frmMainClient", "Chụp màn hình"))
        self.cmd_keystroke.setText(_translate("frmMainClient", "Keystroke"))
        self.cmd_RegisterEdit.setText(_translate("frmMainClient", "Sửa Registry"))
        self.cmd_Quit.setText(_translate("frmMainClient", "Thoát"))
        self.label.setText(_translate("frmMainClient", "Nhập IP:"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    frmMainClient = QtWidgets.QMainWindow()
    ui = Ui_frmMainClient()
    ui.setupUi(frmMainClient)
    frmMainClient.show()
    sys.exit(app.exec_())
Click Run, chúng ta sẽ có được thành quả chạy ra được giao diện GUI như trên. Và bước tiếp theo là chúng ta truyền các biến cố xử lý cho các nút nữa là xong phần đồ án này nhé.

2.2. Xây dựng Back-End.

Tiếp theo chúng ra sẽ xây dựng phần xử lí,

a) Button [Kết nối]

b) Button [Tắt máy]

c) Button [Chụp màn hình]

d) Button [Sửa Registry]

e) Button [Thoát]

def cmd_Quit_Click(self):
    MessageBox = ctypes.windll.user32.MessageBoxW
    MessageBox(None, 'Quit application at client side', 'CLIENT WARNINGS', 0)
    #print("Quit application at client side")
    quit()

f) Button [App Running]

g) Button [Process Running]

h) Button [Key stroke]

By ThanhVL

Leave a Reply