A comprehensive example after learning PyQt

Posted by master82 on Sun, 16 Jan 2022 07:33:02 +0100


catalogue

preface

1, Purpose and function

2, Steps

        1. Use QT designer to build graphics

2.ui file to py file

3. Add fuel to the py file generated by pyuic

4. Create the main file and constructor

 III Problems and experience encountered

 IV Result display

preface

From the beginning of learning programming, I always wanted to build a gui interface that was not a command line, but I only knew c language at that time, so it was a little complicated to use gui. However, this is not what it used to be. With the deepening of python technology, we can gradually understand the use of pyQT.

The following is a comprehensive product after a period of learning.

1, Purpose and function

  1. Build a basic GUI interface to send POST and GET requests.
  2. Set background picture, transparency, etc.
  3. Make secondary changes to the code generated by QT designer and pyuic

2, Steps

1. Use QT designer to build graphics

The process will not be repeated.

The interface is as follows:

 

2.ui file to py file

Because the editor uses VS Code, it configures its own tasks, tasks json

      {
            "label": "PyUIC",
            "type": "shell",
            "command": "C:\\Users\\haost\\PycharmProjects\\pythonProject\\venv\\Scripts\\pyuic5.exe ${file} -o ${cwd}\\QT\\${fileBasenameNoExtension}_rc.py  -x&&py C:\\Users\\haost\\Desktop\\temp\\PY\\QT\\Form_trans.py -i ${file}",
            "problemMatcher": [],
            "group": {
                "kind": "build",
                "isDefault": true
            }
   

Note the &&py C: \ \ users \ \ haost \ \ desktop \ \ temp \ \ py \ \ QT \ \ form_ trans. py -i ${file}

Form_trans.py content will be given later.

My complete tasks JSON is as follows:

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "echo",
            "type": "shell",
            "command": "py --version "
        },
        {
            "label": "qt design",
            "type": "process",
            "command": "C:\\Users\\haost\\PycharmProjects\\pythonProject\\venv\\Lib\\site-packages\\qt5_applications\\Qt\\bin\\designer.exe"
        },
        {
            "label": "PyUIC",
            "type": "shell",
            "command": "C:\\Users\\haost\\PycharmProjects\\pythonProject\\venv\\Scripts\\pyuic5.exe ${file} -o ${cwd}\\QT\\${fileBasenameNoExtension}_rc.py  -x&&py C:\\Users\\haost\\Desktop\\temp\\PY\\QT\\Form_trans.py -i ${file}",
            "problemMatcher": [],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        },
        {
            "label": "Pyinstaller",
            "type": "shell",
            "command": "C:\\Users\\haost\\AppData\\Local\\Programs\\Python\\Python38\\Scripts\\pyinstaller.exe -w -F ${file}"
        }
    ]
    
}

3. Add fuel to the py file generated by pyuic

 Form_trans.py is as follows

#2021.7.21 @haostart
import os
import sys
import re
import argparse


# Build command line parameters and parse them

ap = argparse.ArgumentParser()
ap.add_argument("-i", "--source", required=True)
ap.add_argument("-s", "--space", required=False)
ap.add_argument("-o", "--output", required=False)
args = vars(ap.parse_args())

print(args)


a = args['source'][:-3] + '_rc.py'
with open(a, 'r', encoding='utf-8') as f:
    # content = f.readlines()
    # print(content)
    con = f.read()
    print(re.findall(r'resize.*', con))
    con = con.replace('class Ui_Form(object)',
                      'from PyQt5.QtGui import QPixmap, QPainter\nimport sys,os,random\nclass Ui_Form(QtWidgets.QWidget)')
    con = con.replace('.retranslateUi(Form)',
                      '.retranslateUi(Form)\n        Form.paintEngine()')
    con = con.replace(re.findall(r'resize.*', con)[0], 'resize(1200,800)')
    with open(a[:-3] + '_trans.py', 'w', encoding='utf-8') as m:
        m.write(con)
    # m.close()
    # print(con)
f.close()

This is to introduce more classes into the generated py file and change the window. Repetitive work is eliminated. You can add some fixed things as needed.

Finally, the graphical interface function http_tcp_gui_rc_trans.py is as follows

# -*- coding: utf-8 -*-
#2021.7.21 @haostart
# Form implementation generated from reading ui file 'c:\Users\haost\Desktop\temp\PY\QT\http_tcp_gui.ui'
#
# Created by: PyQt5 UI code generator 5.15.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5 import QtCore, QtGui, QtWidgets


from PyQt5 import QtCore, QtGui, QtWidgets


from PyQt5.QtGui import QPixmap, QPainter


from PyQt5.QtGui import QPixmap, QPainter


class Ui_Form(QtWidgets.QWidget):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(1200, 800)
        self.verticalLayout_4 = QtWidgets.QVBoxLayout(Form)
        self.verticalLayout_4.setObjectName("verticalLayout_4")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setSpacing(1)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.verticalLayout_3 = QtWidgets.QVBoxLayout()
        self.verticalLayout_3.setObjectName("verticalLayout_3")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setContentsMargins(-1, -1, 0, -1)
        self.horizontalLayout_2.setSpacing(0)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.comboBox = QtWidgets.QComboBox(Form)
        self.comboBox.setInsertPolicy(QtWidgets.QComboBox.InsertAtBottom)
        self.comboBox.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents)
        self.comboBox.setIconSize(QtCore.QSize(3, 16))
        self.comboBox.setDuplicatesEnabled(False)
        self.comboBox.setObjectName("comboBox")

        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.horizontalLayout_2.addWidget(self.comboBox)
        self.lineEdit = QtWidgets.QLineEdit(Form)
        self.lineEdit.setText("")
        self.lineEdit.setCursorPosition(0)
        self.lineEdit.setClearButtonEnabled(False)
        self.lineEdit.setObjectName("lineEdit")
        # self.comboBox.setStyleSheet(
        #     "background:transparent;border-width:0;border-style:outset")
        self.horizontalLayout_2.addWidget(self.lineEdit)
        self.verticalLayout_3.addLayout(self.horizontalLayout_2)
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.verticalLayout_5 = QtWidgets.QVBoxLayout()
        self.verticalLayout_5.setContentsMargins(-1, -1, 0, -1)
        self.verticalLayout_5.setObjectName("verticalLayout_5")
        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        self.label = QtWidgets.QLabel(Form)
        self.label.setObjectName("label")
        # self.label.setStyleSheet(
        #     "background:transparent;border-width:0;border-style:outset")
        self.horizontalLayout_3.addWidget(self.label)
        self.lineEdit_2 = QtWidgets.QLineEdit(Form)
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.horizontalLayout_3.addWidget(self.lineEdit_2)
        self.verticalLayout_2.addLayout(self.horizontalLayout_3)
        self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_4.setContentsMargins(13, -1, -1, -1)
        self.horizontalLayout_4.setSpacing(0)
        self.horizontalLayout_4.setObjectName("horizontalLayout_4")
        self.label_2 = QtWidgets.QLabel(Form)
        self.label_2.setObjectName("label_2")
        # self.label_2.setStyleSheet(
        #     "background:transparent;border-width:0;border-style:outset")
        self.horizontalLayout_4.addWidget(self.label_2)
        self.lineEdit_3 = QtWidgets.QLineEdit(Form)
        self.lineEdit_3.setObjectName("lineEdit_3")
        self.horizontalLayout_4.addWidget(self.lineEdit_3)
        self.verticalLayout_2.addLayout(self.horizontalLayout_4)
        self.verticalLayout_5.addLayout(self.verticalLayout_2)
        self.add_sure = QtWidgets.QPushButton(Form)
        self.add_sure.setObjectName("add_sure")
        self.verticalLayout_5.addWidget(self.add_sure)
        self.verticalLayout.addLayout(self.verticalLayout_5)
        self.tableWidget = QtWidgets.QTableWidget(Form)
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setWindowOpacity(0.5)
        self.tableWidget.setStyleSheet(
            "background-color:rgba(244,244,244,100);border-width:0;border-style:outset")
        # self.tableWidget.setStyleSheet(
        #     "background:transparent;border-width:0;border-style:outset")
        self.tableWidget.setColumnCount(2)
        self.tableWidget.setRowCount(0)
        item = QtWidgets.QTableWidgetItem()
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(True)
        font.setUnderline(False)
        font.setWeight(75)
        font.setStrikeOut(False)
        font.setKerning(True)
        item.setFont(font)
        self.tableWidget.setColumnWidth(0, 210)
        self.tableWidget.setHorizontalHeaderItem(0, item)
        item = QtWidgets.QTableWidgetItem()
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(True)
        font.setWeight(75)
        item.setFont(font)
        self.tableWidget.setColumnWidth(1, 250)
        self.tableWidget.setHorizontalHeaderItem(1, item)
        self.verticalLayout.addWidget(self.tableWidget)
        self.verticalLayout_3.addLayout(self.verticalLayout)
        self.horizontalLayout.addLayout(self.verticalLayout_3)
        self.textBrowser = QtWidgets.QTextBrowser(Form)
        self.textBrowser.setObjectName("textBrowser")
        self.tableWidget.setWindowOpacity(0.5)
        self.textBrowser.setStyleSheet(
            "background-color:rgba(244,244,244,100);border-width:0;border-style:outset")
        self.horizontalLayout.addWidget(self.textBrowser)
        self.verticalLayout_4.addLayout(self.horizontalLayout)
        self.horizontalLayout_6 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_6.setSizeConstraint(
            QtWidgets.QLayout.SetFixedSize)
        self.horizontalLayout_6.setContentsMargins(80, 5, 80, 5)
        self.horizontalLayout_6.setSpacing(30)
        self.horizontalLayout_6.setObjectName("horizontalLayout_6")
        self.send = QtWidgets.QPushButton(Form)
        self.send.setCheckable(False)
        self.send.setObjectName("send")
        self.horizontalLayout_6.addWidget(self.send)
        self.exit = QtWidgets.QPushButton(Form)
        self.exit.setAutoDefault(False)
        self.exit.setObjectName("exit")
        self.horizontalLayout_6.addWidget(self.exit)
        self.verticalLayout_4.addLayout(self.horizontalLayout_6)

        self.retranslateUi(Form)
        Form.paintEngine()

        QtCore.QMetaObject.connectSlotsByName(Form)
        # self.paintEvent(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.comboBox.setItemText(0, _translate("Form", "POST"))
        self.comboBox.setItemText(1, _translate("Form", "GET"))
        self.lineEdit.setPlaceholderText(_translate("Form", "Please enter host address"))
        self.label.setText(_translate("Form", "name:"))
        self.label_2.setText(_translate("Form", "value:"))
        self.add_sure.setText(_translate("Form", "OK to add"))
        item = self.tableWidget.horizontalHeaderItem(0)
        item.setText(_translate("Form", "data name"))
        item = self.tableWidget.horizontalHeaderItem(1)
        item.setText(_translate("Form", "value"))
        self.send.setText(_translate("Form", "send out"))
        self.send.setShortcut(_translate("Form", "Return"))
        self.exit.setText(_translate("Form", "sign out"))
        self.exit.clicked.connect(Form.exit)
        self.send.clicked.connect(Form.send)


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

4. Create the main file and constructor

        

#2021.7.21 @haostart
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QDialog, QApplication, QWidget, QLabel, QPushButton, QVBoxLayout
from PyQt5.QtCore import QSize, Qt, QPoint



import json
import sys
import os
import pprint
import requests
import urllib
import urllib.request

from http_tcp_gui_rc_trans import Ui_Form

from PyQt5.QtGui import QPixmap, QPainter, QBrush, QColor


class MainWindow(QWidget):
    def paintEvent(self, e):

        self.painter = QPainter()
        self.painter.begin(self)
        self.painter.setRenderHint(QPainter.Antialiasing)

        rect = self.rect()

        self.pixmap = QPixmap("gelin1.png").scaled(rect.size()) #Background picture, change it yourself

        self.painter.drawPixmap(rect, self.pixmap)

        self.painter.end()

    def mousePressEvent(self, event):

        if (event.button() == QtCore.Qt.LeftButton):
            self.m_startPoint = self.frameGeometry().topLeft() - event.globalPos()

    def mouseMoveEvent(self, event):

        # /* move window */
        self.move(event.globalPos() + self.m_startPoint)

    def __init__(self, parent=None):
        super(QWidget, self).__init__(parent)
        # Use the ui file to import and define the interface class
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        # self.setWindowState(QtCore.Qt.WindowMaximized)

        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)  # Set borderless window
        self.setAttribute(Qt.WA_TranslucentBackground)  # Set background transparency
        # self.setStyleSheet(
        #     "border-radius: 15px;")
        self.data = {}
        self.ui.textBrowser.setFontPointSize(40)
        self.ui.textBrowser.setText('@Haostart')
        # self.paintEngine()

    def exit(self) -> bool:
        return super().close()

    def jsonDataToUrlParams(self, params_data):
        url_str = '?'
        nums = 0
        max_nums = len(params_data)
        for key in params_data:
            nums = nums + 1
            # If it's the last one, don't bring it&
            # Spell as url string
            if nums == max_nums:
                url_str += str(key) + '=' + str(params_data[key])
            else:
                url_str += str(key) + '=' + str(params_data[key]) + '&'
        return url_str

    def get(self):
        print('get')
        host = self.ui.lineEdit.text()
        headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'}
        data = self.data
        host = host + self.jsonDataToUrlParams(data)
        response = requests.get(host, headers=headers)
        content = response.content.decode('utf-8')
        content_text = response.text
        print(content)

        self.ui.textBrowser.setText(content_text)

    def post(self):

        host = self.ui.lineEdit.text()
        headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'}
        response = requests.post(host, headers=headers, data=self.data)
        content = response.content.decode('utf-8')
        content_text = response.text
        print(content)

        self.ui.textBrowser.setText(content_text)

    def send(self):
        cur_choose = self.ui.comboBox.currentText()
        if cur_choose == 'POST':
            self.post()
        elif cur_choose == 'GET':
            self.get()

    def add(self):
        data_name = self.ui.lineEdit_2.text()
        data_val = self.ui.lineEdit_3.text()
        if data_name != '':
            self.ui.table.insertRow(0)
            self.ui.item = QtWidgets.QTableWidgetItem()
            # self.ui.font = QtGui.QFont()
            # self.ui.font.setPointSize(8)
            # self.ui.font.setBold(True)
            # self.ui.font.setWeight(75)
            # self.ui.item.setFont(self.ui.font)

            self.ui.item.setText(data_name)
            self.ui.tableWidget.setItem(0, 0, self.ui.item)
            self.ui.item = QtWidgets.QTableWidgetItem()
            self.ui.item.setText(data_val)
            self.ui.tableWidget.setItem(0, 1, self.ui.item)

            # self.data.setdefault(self.ui.lineEdit_2.text(),
            #                      self.ui.lineEdit_3.text())
            self.data[data_name] = data_val
        print(self.data)
        # self.data_json = json.loads(self.data)

    def delr(self):
        try:
            data_name = self.ui.table.item(
                self.ui.table.currentRow(), 0).text()
            self.data.pop(data_name)
            # print(data_name)
            print(self.data)
            self.ui.table.removeRow(self.ui.table.currentRow())
        except:
            print('error')


if __name__ == "__main__":

    app = QApplication(sys.argv)
    Form = MainWindow()

    Form.show()
    sys.exit(app.exec_())

In this way, a gui interface with background pictures was born, in which the control uses setStyleSheet to set transparent styles.

self.label.setStyleSheet("background:transparent;border-width:0;border-style:outset")

III Problems and experience encountered

1. Studied the layout

 

2. How to call between the drawing file generated by qt and the self established main file

3. Have a deeper understanding of class

4. How to set background picture, transparency, window fillet, etc

5. The use of qt various controls is naturally more skilled

IV Result display

The rounded corners are PS,,, because the window background is set to be transparent, so the picture is displayed directly.

Unfortunately, I can't make the normal picture rounded (I can't do it)

Topics: Python script Visual Studio Code