pyqt

pyqt极速入门

安装

安装pyqt
pip install pyqt5

安装简化版qt designer
https://build-system.fman.io/qt-designer-download

qt designer

先用qt designer画框

然后将ui转为py代码

pyuic5 -o destination.py original.ui 

ui demo

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'C:\Users\david\Desktop\untitled.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# 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


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(808, 508)
        self.textBrowser = QtWidgets.QTextBrowser(Form)
        self.textBrowser.setGeometry(QtCore.QRect(10, 230, 781, 291))
        self.textBrowser.setObjectName("textBrowser")
        self.groupBox = QtWidgets.QGroupBox(Form)
        self.groupBox.setGeometry(QtCore.QRect(10, 20, 781, 181))
        self.groupBox.setTitle("")
        self.groupBox.setObjectName("groupBox")
        self.label = QtWidgets.QLabel(self.groupBox)
        self.label.setGeometry(QtCore.QRect(10, 30, 54, 12))
        self.label.setObjectName("label")
        self.pushButton = QtWidgets.QPushButton(self.groupBox)
        self.pushButton.setGeometry(QtCore.QRect(454, 22, 71, 31))
        self.pushButton.setObjectName("pushButton")
        self.lineEdit = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit.setGeometry(QtCore.QRect(90, 20, 291, 31))
        self.lineEdit.setObjectName("lineEdit")
        self.pushButton_2 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_2.setGeometry(QtCore.QRect(540, 20, 81, 31))
        self.pushButton_2.setObjectName("pushButton_2")
        self.label_2 = QtWidgets.QLabel(Form)
        self.label_2.setGeometry(QtCore.QRect(10, 210, 54, 12))
        self.label_2.setObjectName("label_2")

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

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "script boy tools"))
        self.label.setText(_translate("Form", "url"))
        self.pushButton.setText(_translate("Form", "attack"))
        self.pushButton_2.setText(_translate("Form", "stop"))
        self.label_2.setText(_translate("Form", "log"))

将designer.py和编写逻辑的py放在同一目录,以便引用

test.py

import sys
from PyQt5.QtWidgets import QApplication, QWidget
from designer import Ui_Form


class Demo(QWidget, Ui_Form):
    def __init__(self):
        super(Demo, self).__init__()
        self.setupUi(self)                                          # 1
        self.text_edit.textChanged.connect(self.show_text_func)     # 2

    def show_text_func(self):
        self.text_browser.setText(self.text_edit.toPlainText())


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())
  1. 将UI界面布局到Demo上;

  2. 将self.text_edit的textChanged信号连接到自定义的槽函数上,在槽函数中我们将self.text_browser的文本设为self.text_edit的文本。

signal和slot

pyqt核心就是信号和槽,用来传递指令和执行指令

控件有很多属性,比如说按钮被点击,点击就是一种信号,可以连接槽函数来执行内容

这是一个信号连接一个槽连接的例子

还有多个信号连接一个槽、信号连接信号、一个信号连接多个槽、自定义信号

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton


class Demo(QWidget):                                            # 1
    def __init__(self):
        super(Demo, self).__init__()
        self.button = QPushButton('Start', self)                # 2
        self.button.clicked.connect(self.change_text)           # 3

    def change_text(self):
        print('change text')
        self.button.setText('Stop')                             # 4
        self.button.clicked.disconnect(self.change_text)        # 5


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()                                               # 6
    demo.show()                                                 # 7
    sys.exit(app.exec_())

在线程中获取窗口内容

ui线程只能用来跑ui,要执行业务逻辑得多开一个线程,防止窗口阻塞

获取输入框的内容

import sys
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLineEdit, QLabel, QVBoxLayout, QHBoxLayout


class Demo(QWidget):
    def __init__(self):
        super(Demo, self).__init__()
        self.line = QLineEdit()
        self.btn = QPushButton('开始爬取')
        self.btn.clicked.connect(self.start_slot)

        h_layout = QHBoxLayout()
        v_layout = QVBoxLayout()
        h_layout.addWidget(QLabel('网址:'))
        h_layout.addWidget(self.line)
        v_layout.addLayout(h_layout)
        v_layout.addWidget(self.btn)
        self.setLayout(v_layout)

        self.crawl_thread = CrawlThread(self)  # 1

    def start_slot(self):  # 2
        self.crawl_thread.start()


class CrawlThread(QThread):
    def __init__(self, demo):  # 3
        super(CrawlThread, self).__init__()
        self.demo = demo

    def run(self):  # 4
        url = self.demo.line.text().strip()
        print(f'要爬取的网址为:{url}')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())
  1. 实例化线程,注意此时我们需要把当前窗口类实例(也就是self)传入。

  2. 按钮所连接的槽函数用来启动线程。

  3. 给线程的初始化函数添加一个参数,用来获取窗口类实例。

  4. 接着我们就可以在run函数中获取窗口上任何一个控件及其内容了。

子线程数据输入到控件

这里发起请求包的子线程的返回值输出到textbrowser控件上,txetbrowser就变成一个打印日志的框

用到了自定义信号来实现线程间通信

import sys
from PyQt5.QtWidgets import QApplication, QWidget
from destination import Ui_Form
import requests
from PyQt5.QtCore import Qt, QThread, pyqtSignal

class Demo(QWidget, Ui_Form):
    def __init__(self):
        super(Demo, self).__init__()
        self.setupUi(self)  
        self.pushButton.clicked.connect(self.login)
        self.my_thread = MyThread(self) # 1
        self.my_thread.child_signal.connect(self.log) # 2

    def log(self, msg): # 5
        self.textBrowser.append(msg)
        # self.textBrowser.setText(msg)

    def login(self):
        self.my_thread.start()



class MyThread(QThread):
    child_signal = pyqtSignal(str)  # 3

    def __init__(self, demo):
        super(MyThread, self).__init__()
        self.demo = demo

    def buy(self):
        print('buy')

    def run(self): 
        # phone = self.demo.textEdit.toPlainText()
        # print(phone)

        while 1:
            res=requests.get("http://www.baidu.com")

        # self.demo.textBrowser.setText(phone)
        # self.sig.emit(phone)
            self.child_signal.emit(res.text) # 4

class Send(QThread):
    pass

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())
  1. 实例化线程对象
  2. 线程自定义信号连接槽函数
  3. 自定义信号对象,str表示这个信号可以传递一个参数
  4. 自定义信号将结果发射出去
  5. 结果传递给槽函数
updatedupdated2023-01-012023-01-01