1、pyqt界面的操作主要有QPushButton按钮、QLabel标签、QLineEdit文本编辑、QPixmap图像载入与QLabel联用、QTableWidget(19,3)表格等,界面的刷新主要是对标签、文本、图像、表格等相关数据进行刷新。有了这些基本的搭建功能模块,我们需要通过QGridLayout()、QFormLayout()、QBoxLayout()等Layout将这些模块按照自己的需要组装起来,再通过QVBoxLayout()竖向添加模块、QHBoxLayout()横向添加模块这两个模块来实现整个界面的布局。通过信号与槽来实现界面与界面之间的通信,利用多线程多进程来解决界面卡顿的问题。学会了这些,一般的界面搭建就没有问题了。

2、界面传值:

        如果遇到想做来两个界面之间的传值,在父界面中,通过self.widget调用子界面中的SendEdit等参数进行传递。

        子界面

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# author:SingWeek
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys

class prowler(QWidget):
    switchSig =pyqtSignal(dict)
    def __init__(self, parent=None):
        super(prowler, self).__init__(parent)

        self.sendData={"first":"I", "second":"Love", "third":"You"}

        self.SendBtn = QPushButton("向父界面传值1")
        self.SendEdit=QLineEdit()
        self.SendBtn1 = QPushButton("向父界面传值2")
        self.SendEdit1=QLineEdit()

        layout=QGridLayout()
        layout.addWidget(self.SendBtn,0,0)
        layout.addWidget(self.SendEdit,0,1)
        layout.addWidget(self.SendBtn1,1,0)
        layout.addWidget(self.SendEdit1,1,1)



        QHBLayout = QHBoxLayout()
        QVBLayout = QVBoxLayout()

        QHBLayout.addLayout(layout)
        QVBLayout.addLayout(QHBLayout)

        self.setLayout(QVBLayout)
        self.SendBtn.clicked.connect(self.SendData)
        self.SendBtn1.clicked.connect(self.SendData1)

        self.setWindowTitle("Son")

    def SendData(self):
        tmp=self.SendEdit.text()
        print("向父界面发送的值",tmp)
        self.sendData["first"]=tmp
        print("向父界面发送的字典",self.sendData)
        self.switchSig.emit(self.sendData)

    def SendData1(self):
        tmp=self.SendEdit1.text()
        print("向父界面发送的值",tmp)
        self.sendData["second"]=tmp
        print("向父界面发送的字典",self.sendData)
        self.switchSig.emit(self.sendData)


if __name__=="__main__":
    app = QApplication(sys.argv)
    Jenney = prowler()
    Jenney.show()
    sys.exit(app.exec_())

        父界面

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# author:SingWeek
from PyQt5.QtWidgets import *
import sys
from UI.字典传值子界 import prowler#子界面的py文件的位置,函数导入自己根据文件名和位置修改

class main(QWidget):
    def __init__(self, parent=None):
        super(main, self).__init__(parent)

        self.sendData = {"first": "I", "second": "Love", "third": "You"}

        self.OpenBtn = QPushButton("呼唤子界面")
        self.OpenEdit=QLineEdit()
        self.ShowBtn = QPushButton("显示")
        self.ShowEdit=QLineEdit()
        self.ShowBtn1 = QPushButton("显示1")
        self.ShowEdit1=QLineEdit()

        layout=QGridLayout()
        layout.addWidget(self.OpenBtn,0,0)
        layout.addWidget(self.OpenEdit,0,1)
        layout.addWidget(self.ShowBtn,1,0)
        layout.addWidget(self.ShowEdit,1,1)
        layout.addWidget(self.ShowBtn1,2,0)
        layout.addWidget(self.ShowEdit1,2,1)

        QHBLayout = QHBoxLayout()
        QVBLayout = QVBoxLayout()

        QHBLayout.addLayout(layout)
        QVBLayout.addLayout(QHBLayout)

        self.setLayout(QVBLayout)

        self.OpenBtn.clicked.connect(self.Connect)
        self.setWindowTitle("Father")

    def Connect(self):
        self.widget = prowler()
        self.widget.show()
        self.widget.switchSig.connect(self.reaction)

    def reaction(self, string):
        print("父界面接收到的字典",string)
        self.sondata=string
        tmp=self.sondata["first"]
        print("父界面接收到的值",tmp)
        self.ShowEdit.setText(tmp)
        tmp1=self.sondata["second"]
        print("父界面接收到的值1", tmp1)
        self.ShowEdit1.setText(tmp1)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    Jenney = main()
    Jenney.show()
    sys.exit(app.exec_())

        信号与槽的触发,可以用来界面刷新,class UpdateData(QThread):来设置触发信号,def update_item_data(self, data):接收信号的值,通过在main中将他们关联起来myTable可以用自己的界面函数替换掉,后面更多是需要触发的相应函数。

# 启动更新线程
    update_data_thread = UpdateData()
    update_data_thread.update_date.connect(myTable.update_item_data)  # 链接信号
    update_data_thread.start()
# code:utf-8
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
import time


class MyTable(QTableWidget):
    def __init__(self, parent=None):
        super(MyTable, self).__init__(parent)
        self.setWindowTitle("各个市场比特币实时行情")  # 设置表格名称
        self.setWindowIcon(QIcon("ok.png"))  # 设置图标(图片要存在)
        self.resize(600, 200)  # 设置表格尺寸(整体大小)
        self.setColumnCount(5)  # 设置列数
        self.setRowCount(5)  # 设置行数
        # self.setColumnWidth(0, 200)  # 设置列宽(第几列, 宽度)
        # self.setRowHeight(0, 100)  # 设置行高(第几行, 行高)
     
        column_name = [
            'ETH/BIC',
            'column1',
            'column2',
            'column3',
            'column4',
        ]
        self.setHorizontalHeaderLabels(column_name)  # 设置列名称
        row_name = [
            'binance',
            'okex',
            'bitfinex',
            'bittrex',
            'bithumb',
        ]
        self.setVerticalHeaderLabels(row_name)  # 设置行名称

    def update_item_data(self, data):
        """更新内容"""
        self.setItem(0, 0, QTableWidgetItem(data)) # 设置表格内容(行, 列) 文字


class UpdateData(QThread):
    """更新数据类"""
    update_date = pyqtSignal(str)  # pyqt5 支持python3的str,没有Qstring

    def run(self):
        cnt = 0
        while True:
            cnt += 1
            self.update_date.emit(str(cnt))  # 发射信号
            time.sleep(1)


if __name__ == '__main__':
    # 实例化表格
    app = QApplication(sys.argv)
    myTable = MyTable()
    # 启动更新线程
    update_data_thread = UpdateData()
    update_data_thread.update_date.connect(myTable.update_item_data)  # 链接信号
    update_data_thread.start()

    # 显示在屏幕中央
    desktop = QApplication.desktop()  # 获取坐标
    x = (desktop.width() - myTable.width()) // 2
    y = (desktop.height() - myTable.height()) // 2
    myTable.move(x, y)  # 移动

    # 显示表格
    myTable.show()
    app.exit(app.exec_())

3、图像载入

logoLabel = QLabel()
        logopixMap = QPixmap(".//img//logo.jpg")#载入图像的位置
        logoLabel.setPixmap(logopixMap)

4、相关博客界面刷新参考原文:如果本文没有帮你解决问题,希望能从这些参考博客中解决你的问题。

   

5、界面表格、文本刷新

self.creatMessageline()
        mainLayout = QVBoxLayout()
        hboxLayout = QHBoxLayout()
        hboxLayout.addStretch()
        # hboxLayout.addWidget()#横向添加模块
        mainLayout.addLayout(hboxLayout)
        mainLayout.addWidget(self.Headline)#纵向添加模块
        self.setLayout(mainLayout)
        self.setWindowTitle('测试')
    def creatMessageline(self):
        self.recv_id=["simple"]
        self.test_data = ["simple"]
        self.Messageline = QGroupBox("信息:")
        layout = QFormLayout()
        testitemLabel = QLabel("测试:")
        testitemEditor = QLabel(self.testitemInformation)
        testitemEditor.setFont(QFont("Roman times",10,QFont.Bold))
        pe = QPalette()#样式设置
        pe.setColor(QPalette.WindowText, Qt.red)  # 设置字体颜色
        testitemEditor.setPalette(pe)
        self.table = QTableWidget(99,3)
        self.table.setHorizontalHeaderLabels(["编号","测试","人员"])
        for i in range(len(self.recv_id)):
            self.table.setItem(i,0,QTableWidgetItem(str(self.recv_id[i])))
            self.table.setItem(i,1,QTableWidgetItem(str(self.test_data[i])))
            self.table.setItem(i,2,QTableWidgetItem("auto"))
        row_count = self.table.rowCount()
        self.table.insertRow(row_count)
        layout.addRow(testitemLabel,testitemEditor)
        layout.addRow(self.table)
        self.Messageline.setLayout(layout)

        表格绘制中有一行代码请注意:self.table.setItem(i,0,QTableWidgetItem(str(self.recv_id[i]))),(重新调用一次for循环代码)我们可以直接通过这个来对表格进行刷新,通过for循环遍历表格,通过QTableWidgetItem中带不同参数将表格数据更新成对应的参数。

        文本等数据的更新一般来说可以直接self.testEdit.setText("OK")来进行参数更新。这里的更新需要相应触发才能实现,比如果按键、时钟、信号与槽之类、多线程等。pyqt5界面的多线程可以参考:

        

6、字体设置

        界面字体设置:

testitemEditor = QLabel("test")
        testitemEditor.setFont(QFont("Roman times",10,QFont.Bold))#设置字体大小样式
        pe = QPalette()#样式设置
        pe.setColor(QPalette.WindowText, Qt.red)  # 设置字体颜色
        testitemEditor.setPalette(pe)

        通过按钮点击选择来设置字体的,选择的字体样式比较全面,通常用于文本编辑。

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# author:SingWeek

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import sys
class Example(QWidget):
    def __init__(self):
        super().__init__()

        self.initUI()
    def initUI(self):

        self.setGeometry(300, 300, 500, 400)
        self.setWindowTitle('字体设置')

        self.tx = QTextEdit(self)
        self.tx.setGeometry(20, 20, 300, 300)

        self.bt1 = QPushButton('打开文件',self)
        self.bt1.move(350,20)
        self.bt2 = QPushButton('选择字体',self)
        self.bt2.move(350,70)
        self.bt3 = QPushButton('选择颜色',self)
        self.bt3.move(350,120)
        self.bt4=QPushButton('更改背景',self)
        self.bt4.move(350,170)
        self.bt5 = QPushButton('图像背景',self)
        self.bt5.move(350,220)
        self.bt6=QPushButton('文字背景',self)
        self.bt6.move(350,270)


        self.bt1.clicked.connect(self.openfile)
        self.bt2.clicked.connect(self.choicefont)
        self.bt3.clicked.connect(self.choicecolor)
        self.bt4.clicked.connect(self.BackgroundColor)
        self.bt5.clicked.connect(self.Backgroundimg)
        self.bt6.clicked.connect(self.testbackground)

        self.show()
    def openfile(self):
        fname = QFileDialog.getOpenFileName(self, '打开文件','./')
        if fname[0]:
            with open(fname[0], 'r',encoding='gb18030',errors='ignore') as f:
                self.tx.setText(f.read())
    def choicefont(self):#字体设置
        font, ok = QFontDialog.getFont()
        if ok:
            self.tx.setCurrentFont(font)
    def choicecolor(self):
        col = QColorDialog.getColor()
        if col.isValid():
            #self.tx.setTextColor(Qt.red)#根据自己的需要设置颜色
            self.tx.setTextColor(col)#可以自己选择需要的颜色
    def BackgroundColor(self):
        self.tx.setStyleSheet("background:blue")#自己输入需要的颜色
    def Backgroundimg(self):
        self.tx.setStyleSheet("background-image:url(img.jpg)")#需要输入正确的图像地址
    def testbackground(self):
        self.tx.setTextBackgroundColor(QColor(255, 0, 0))#需要自己设置颜色
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

7、界面中的多线程

#创建一个线程
class Correcte(QThread):
    def __init__(self, data,parent=None):
        super(Correcte, self).__init__(parent)
        self.working = True
        self.data=data
    def __del__(self):
        self.working = False
        self.wait()
    def run(self):#通过QThread重载线程
        if self.working == True:
            Current_Correction(self.data)

#通过按钮启动停止这个线程
self.Correction_num=0
def Start(self):
    self.thread = Correcte(self.recv_id)
    if self.Correction_num==0:
        self.thread.start()
        self.Correction_num+=1
        #self.test_start.setText("点击停止")
    else:
        self.thread.quit()
        self.Correction_num=0
        #self.test_start.setText("KB校正")

8、python日志参数

import logging
import time
nowtime = time.localtime()
monthtime = time.strftime("%m", nowtime)
yeartime = time.strftime("%Y", nowtime)
logstime = time.strftime("%Y-%m-%d-%H", nowtime)
logging.basicConfig(filename='./log/'+yeartime+'/'+monthtime +'/'+'access'+str(logstime) + '.log', level=logging.INFO)
logging.info(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+':info级别,一般用来打印一些正常的操作信息')
logging.critical(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+':critical级别,一般用来打印一些致命的错误信息,等级最高')
logging.debug(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+':debug级别,一般用来打印一些调试信息,级别最低')
logging.error(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+':rror级别,一般用来打印一些错误信息')
logging.warning(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+':waring级别,一般用来打印警告信息')

9、界面卡顿:在QThread中加入QApplication.processEvents()进行界面刷新,通过pyqtSignal进行值的传递。

#!usr/bin/python3
# -*- coding:utf-8 -*-
# author:SingWeek

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys,time

class MyTable(QTableWidget):
    def __init__(self, parent=None):
        super(MyTable, self).__init__(parent)
        self.setWindowTitle("Test")  # 设置表格名称
        # self.resize(600, 200)  # 设置表格尺寸(整体大小)
        self.Config_Set = QGroupBox("Test")
        self.Text=QLineEdit("显示")
        self.CBtn = QPushButton("开始")
        self.Click=QPushButton("打印")
        self.NTime=QLineEdit("")
        layout = QGridLayout()
        layout.addWidget(self.CBtn,1,1)
        layout.addWidget(self.Text,2,1)
        layout.addWidget(self.Click,3,1)
        layout.addWidget(self.NTime,4,1)
        self.Config_Set.setLayout(layout)

        mainLayout = QVBoxLayout()
        hboxLayout = QHBoxLayout()
        hboxLayout.addStretch()
        hboxLayout.addWidget(self.Config_Set)#横向添加表格块
        mainLayout.addLayout(hboxLayout)
        self.setLayout(mainLayout)

        self.CBtn.clicked.connect(self.Btn)
        self.Click.clicked.connect(self.Print)
    def Print(self):
        self.NTime.setText("当前系统时间"+time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
        print("当前系统时间"+time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

    def Btn(self):
        calcnum=100000
        update_data_thread = UpdateData(calcnum)#
        update_data_thread.update_date.connect(self.update_item_data)  # 链接信号
        update_data_thread.run()

    def update_item_data(self, data):
        """更新内容"""
        self.Text.setText(data)


class UpdateData(QThread):
    """界面和 运行相分离,通过信号与槽来进行参数传递"""
    update_date = pyqtSignal(str)  # pyqt5 支持python3的str,没有Qstring
    def __init__(self,data, parent=None):
        super(UpdateData, self).__init__(parent)
        self.data=data
    def run(self):
        calc(self.data,self.update_date)

def calc(data,update_date):
    """
    下面可以是其他相应的功能函数
    :param update_date:
    :return:
    """
    cnt = 0
    while True:
        cnt += 1
        update_date.emit(str(cnt))  # 发射信号
        # time.sleep(1)
        if cnt>=data:
            cnt=0
        QApplication.processEvents()  # 刷新界面,避免卡顿

if __name__ == '__main__':
    app = QApplication(sys.argv)
    myTable = MyTable()
    myTable.show()
    app.exit(app.exec_())

10、界面闪退

def Test(self):
        from SFKYSQL import SQLMainWindow
        self.station1=SQLMainWindow()
        self.station1.show()

        在窗口接的最前方加入self.就可以避免闪退问题,程序示列所示。

11、进程关闭

import threading
import time
import inspect
import ctypes
 
def _async_raise(tid, exctype):
    """raises the exception, performs cleanup if needed"""
    tid = ctypes.c_long(tid)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        # """if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")
 
def stop_thread(thread):
    _async_raise(thread.ident, SystemExit)
 
class TestThread(threading.Thread):
    def run(self):
        print("begin")
        while True:
            time.sleep(0.1)
        print("end")
if __name__ == "__main__":
    t = TestThread()
    t.start()
    time.sleep(1)
    stop_thread(t)#关闭当前线程
    print("stoped")

12、待补充