Java业务逻辑pyqt_PyQt5 UI界面与业务逻辑分离

先说遇到的问题希望遇到和我一样问题的童鞋也可以成功解决。我在处理逻辑业务时候比较耗时经常造成界面未响应!!!。

但是当使用python 的thread时候会造成主界面数据复原,暂时不知道什么原因。之后开始我的学习之路。

因为qt界面的刷新相当于一直while,当有耗时多的任务时就会造成阻塞无法完成刷新,造成界面未响应。

这时候就需要使用Qthread处理业务逻辑,主线程继续处理界面。分离ui界面与业务逻辑。

要使用QThread开始一个线程,可以创建它的一个子类,然后覆盖其QThread.run()函数

class Thread(QThread):

def __init__(self):

super().__init__()

def run(self):

# 线程相关代码

pass

# 创建一个新的线程

thread = Thread()

thread.start()

在使用线程时可以直接得到Thread实例,调用其start()函数即可启动线程,线程启动后,会调用其实现的run方法,该方法就是线程的执行函数,当run()退出之后线程基本就结束了。

QThread类中的常用方法:

start() 启动线程

wait() 阻止线程

sleep(s) 强制当前线程睡眠s秒

QThread类中的常用信号:

started 在开始执行run()函数之前,从相关线程发射此信号

finished 在程序完成业务逻辑时,从相关线程发射此信号

当在窗口中显示的数据比较简单时,可以把读取数据的业务逻辑放在窗口的初始化代码中;但如果读取数据的时间比较长,比如网络请求数据的时间比较长,则可以把这部分逻辑放在QThread线程中,实现界面的数据显示和数据读取的分离.

from PyQt5.QtCore import *

from PyQt5.QtWidgets import *

import sys

class Worker(QThread):

sinOut = pyqtSignal(str) # 自定义信号,执行run()函数时,从相关线程发射此信号

def __init__(self, parent=None):

super(Worker, self).__init__(parent)

self.working = True

self.num = 0

def __del__(self):

self.working = False

self.wait()

def run(self):

while self.working == True:

file_str = 'File index {0}'.format(self.num) # str.format()

self.num += 1

# 发出信号

self.sinOut.emit(file_str)

# 线程休眠2秒

self.sleep(2)

class MainWidget(QWidget):

def __init__(self, parent=None):

super(MainWidget, self).__init__(parent)

self.setWindowTitle("QThread 例子")

# 布局管理

self.listFile = QListWidget()

self.btnStart = QPushButton('开始')

layout = QGridLayout(self)

layout.addWidget(self.listFile, 0, 0, 1, 2)

layout.addWidget(self.btnStart, 1, 1)

# 连接开始按钮和槽函数

self.btnStart.clicked.connect(self.slotStart)

# 创建新线程,将自定义信号sinOut连接到slotAdd()槽函数

self.thread = Worker()

self.thread.sinOut.connect(self.slotAdd)

# 开始按钮按下后使其不可用,启动线程

def slotStart(self):

self.btnStart.setEnabled(False)

self.thread.start()

# 在列表控件中动态添加字符串条目

def slotAdd(self, file_inf):

self.listFile.addItem(file_inf)

if __name__ == "__main__":

app = QApplication(sys.argv)

demo = MainWidget()

demo.show()

sys.exit(app.exec_())

这个经典例子,虽然解决了界面的数据显示和数据读取的分离,但是如果数据的读取非常消耗时间,则会造成界面卡死,下面是一个需要耗费很长时间读取数据的例子。

import sys from PyQt5.QtCore

import * from PyQt5.QtGui

import * from PyQt5.QtWidgets

import * global sec sec = 0

def setTime():

global sec sec += 1

# LED显示数字+1

lcdNumber.display(sec)

def work():

#每秒计数

timer.start(1000)

# 开始一次非常耗时的计算

# 这里用一个2 000 000 000次的循环来模拟

for i in range(200000000):

pass timer.stop()

if __name__ == "__main__":

app = QApplication(sys.argv)

top = QWidget() top.resize(300, 120)

# 垂直布局类

QVBoxLayout layout = QVBoxLayout(top)

# 添加控件

lcdNumber = QLCDNumber()

layout.addWidget(lcdNumber)

button = QPushButton("测试")

layout.addWidget(button)

timer = QTimer()

# 每次计时结束,触发setTime

timer.timeout.connect(setTime)

# 连接测试按钮和槽函数

work button.clicked.connect(work)

top.show()

sys.exit(app.exec_())

程序的运行逻辑如下:

ec52f57ae3d3?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

这里写图片描述

正常情况下,在点击按钮之后,LCD上的数字会随着时间发生变化,但是在实际运行过程中会发现点击按钮之后,程序界面直接停止响应,直到循环结束才开始重新更新,于是计时器始终显示为0。

在上面这个程序中没有引入新的线程,PyQt中所有的窗口都在UI主线程中(就是执行了QApplication.exec()的线程),在这个线程中执行耗时的操作会阻塞UI线程,从而让窗口停止响应。

为了避免出现上述问题,要使用QThread开启一个新的线程,在这个线程中完成耗时的操作:

mport sys

from PyQt5.QtCore import *

from PyQt5.QtGui import *

from PyQt5.QtWidgets import *

global sec

sec = 0

# 增加了一个继承自QThread类的类,重新写了它的run()函数

# run()函数即是新线程需要执行的:执行一个循环;发送计算完成的信号。

class WorkThread(QThread):

trigger = pyqtSignal()

def __int__(self):

super(WorkThread, self).__init__()

def run(self):

for i in range(2000000000):

pass

# 循环完毕后发出信号

self.trigger.emit()

def countTime():

global sec

sec += 1

# LED显示数字+1

lcdNumber.display(sec)

def work():

# 计时器每秒计数

timer.start(1000)

# 计时开始

workThread.start()

# 当获得循环完毕的信号时,停止计数

workThread.trigger.connect(timeStop)

def timeStop():

timer.stop()

print("运行结束用时", lcdNumber.value())

global sec

sec = 0

if __name__ == "__main__":

app = QApplication(sys.argv)

top = QWidget()

top.resize(300, 120)

# 垂直布局类QVBoxLayout

layout = QVBoxLayout(top)

# 加个显示屏

lcdNumber = QLCDNumber()

layout.addWidget(lcdNumber)

button = QPushButton("测试")

layout.addWidget(button)

timer = QTimer()

workThread = WorkThread()

button.clicked.connect(work)

# 每次计时结束,触发 countTime

timer.timeout.connect(countTime)

top.show()

sys.exit(app.exec_())

程序运行逻辑简单说明:

按下按钮后,计时器开始计数,并启动一个新的线程,在这个线程里,执行一个循环并在循环结束时发送完成信号,在完成信号发出后,执行与之相关联的槽函数,关闭定时器。

再次运行程序,界面有了响应。

事件处理

对于执行很耗时的程序来说,由于PyQt需要等待程序执行完毕才能进行下一步,这个过程表现在界面上就是卡顿;而如果在执行这个耗时程序时不断地运行QApplication.processEvents(),那么就可以实现一边执行耗时程序,一边刷新页面的功能,会给人一种相对更流畅的感觉,QApplication.processEvents()的使用方法是,在主函数执行耗时操作的地方,加入QApplication.processEvents(),processEvents()函数的使用方法简单来说就是刷新页面。(可以在table获取数据及时显示等操作使用)

from PyQt5.QtWidgets import QWidget, QPushButton, QApplication, QListWidget, QGridLayout

import sys

import time

class WinForm(QWidget):

def __init__(self, parent=None):

super(WinForm, self).__init__(parent)

self.setWindowTitle("实时刷新界面例子")

self.listFile = QListWidget()

self.btnStart = QPushButton('开始')

layout = QGridLayout(self)

layout.addWidget(self.listFile, 0, 0, 1, 2)

layout.addWidget(self.btnStart, 1, 1)

self.setLayout(layout)

self.btnStart.clicked.connect(self.slotAdd)

def slotAdd(self):

for n in range(10):

str_n = 'File index {0}'.format(n)

self.listFile.addItem(str_n)

QApplication.processEvents()

time.sleep(1)

if __name__ == "__main__":

app = QApplication(sys.argv)

form = WinForm()

form.show()

sys.exit(app.exec_())

如果不添加QApplication.processEvents(),会在卡顿之后全部结果,添加之后,也不能保证每个都是逐行显示,只是比不加相对流畅一点,效果是不如多线程的。

总结

能用多线程尽量用多线程,不论数据处理还是界面流程性都优于QApplication.processEvents(),但是当数据量小的时候可以使用QApplication.processEvents(),代码比较简单。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值