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、待补充