WxPython界面利用pubsub如何实现多线程控制
作者:陈年椰子 发布时间:2021-01-28 08:10:03
标签:WxPython,pubsub,多线程,控制
WxPython界面用pubsub实现多线程控制
用WxPython做界面时, 如果数据操作时间比较长,会使 WxPython 界面处于假死状态,用户体验非常不好。
WxPython是利用pubsub来完成消息的传送。
下面提供一个 WxPython界面利用pubsub 实现2个线程的控制的例子
实际使用, 只要修改WorkThread1、WorkThread2 里的 run 内容 及 MainFrame 里的 updateDisplay 内容即可。
在此基础上,可以实现多线程。
Python 3.7.3
wxPython 4.0.6
Pypubsub 4.0.3
在此之前有个单线程及进度条的例子,简单需求可以参考这个
下面提供本文的代码
# encoding: utf-8
"""
@author: 陈年椰子
@contact: hndm@qq.com
@version: 1.0
@project:test
@file: wx_thread.py
@time: 2022-3-24 15:34
说明
"""
import wx
from pubsub import pub
from time import sleep
import time
import threading
import sys
from random import random
# 线程调用耗时长代码
class WorkThread1(threading.Thread):
def __init__(self):
"""Init Worker Thread Class."""
threading.Thread.__init__(self)
self.breakflag = False
self.start()
def stop(self):
self.breakflag = True
# 耗时长的代码
def workproc(self):
while True:
if self.breakflag:
pub.sendMessage("update", mstatus='查询Thread中断')
sleep(2)
break
ts1 = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
t_sum = "查询的结果"
# print(ts1,t_sum)
# 此处加的数据库代码
pub.sendMessage("update", mstatus='{}:查询最后10个数据并汇总{}'.format(ts1, t_sum))
sleep(10)
pub.sendMessage("update", mstatus='workdone')
return ""
def run(self):
"""Run Worker Thread."""
pub.sendMessage("update", mstatus='workstart')
self.workproc()
# 线程调用耗时长代码
class WorkThread2(threading.Thread):
def __init__(self):
"""Init Worker Thread Class."""
threading.Thread.__init__(self)
self.breakflag = False
self.start()
def stop(self):
self.breakflag = True
# 耗时长的代码
def workproc(self):
while True:
if self.breakflag:
pub.sendMessage("update", mstatus='随机数Thread中断')
sleep(2)
break
ts1 = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
t_info = "随机数{}".format(str(random()))
# print(ts1, t_info)
# 此处加的数据库代码
pub.sendMessage("update", mstatus='{}:产生{}'.format(ts1, t_info))
sleep(1)
pub.sendMessage("update", mstatus='workdone')
return ""
def run(self):
"""Run Worker Thread."""
pub.sendMessage("update", mstatus='workstart')
self.workproc()
class MainFrame(wx.Frame):
"""
简单的界面
"""
def __init__(self, *args, **kw):
# ensure the parent's __init__ is called
super(MainFrame, self).__init__(*args, **kw)
self.SetSize(size=(600, 400))
# create a panel in the frame
pnl = wx.Panel(self)
# and put some text with a larger bold font on it
self.st = wx.StaticText(pnl, label="分析工具 V 2022", pos=(25, 25))
self.st2 = wx.StaticText(pnl, label="提示", pos=(25, 80))
font = self.st.GetFont()
font.PointSize += 2
font = font.Bold()
self.st.SetFont(font)
self.st2.SetFont(font)
# create a menu bar
self.makeMenuBar()
self.gauge = wx.Gauge(self, range=100, size=(500, 20))
self.gauge.SetBezelFace(3)
self.gauge.SetShadowWidth(3)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.st, 0, wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, 0)
sizer.Add(self.st2, 0, wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, 0)
sizer.Add(self.gauge, 0, wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, 0)
self.SetSizer(sizer)
# and a status bar
self.CreateStatusBar()
self.SetStatusText("启动完成!")
pub.subscribe(self.updateDisplay, "update")
def makeMenuBar(self):
"""
A menu bar is composed of menus, which are composed of menu items.
This method builds a set of menus and binds handlers to be called
when the menu item is selected.
"""
# Make a file menu with Hello and Exit items
fileMenu = wx.Menu()
# The "\t..." syntax defines an accelerator key that also triggers
# the same event
# helloItem = fileMenu.Append(-1, "&Hello...\tCtrl-H",
# "Help string shown in status bar for this menu item")
self.startItem = fileMenu.Append(-1, "开始",
"开始工作")
self.stopItem = fileMenu.Append(-1, "停止",
"中断工作")
fileMenu.AppendSeparator()
self.exitItem = fileMenu.Append(-1, "退出",
"退出")
# Now a help menu for the about item
helpMenu = wx.Menu()
aboutItem = helpMenu.Append(-1, "关于",
"WxPython 界面与线程通讯的例子")
# Make the menu bar and add the two menus to it. The '&' defines
# that the next letter is the "mnemonic" for the menu item. On the
# platforms that support it those letters are underlined and can be
# triggered from the keyboard.
self.menuBar = wx.MenuBar()
self.menuBar.Append(fileMenu, "工作")
self.menuBar.Append(helpMenu, "信息")
# Give the menu bar to the frame
self.SetMenuBar(self.menuBar)
self.stopItem.Enable(False)
self.count = 0
# Finally, associate a handler function with the EVT_MENU event for
# each of the menu items. That means that when that menu item is
# activated then the associated handler functin will be called.
self.Bind(wx.EVT_MENU, self.OnStart, self.startItem)
self.Bind(wx.EVT_MENU, self.OnStop, self.stopItem)
self.Bind(wx.EVT_MENU, self.OnExit, self.exitItem)
self.Bind(wx.EVT_MENU, self.OnAbout, aboutItem)
def OnExit(self, event):
"""Close the frame, terminating the application."""
try:
self.work1.stop()
self.work2.stop()
sleep(2)
except:
pass
self.Close(True)
sys.exit()
def OnStart(self, event):
self.work1 = WorkThread1()
self.work2 = WorkThread2()
def OnStop(self, event):
self.work1.stop()
self.work2.stop()
def OnAbout(self, event):
"""Display an About Dialog"""
wx.MessageBox("分析工具 v2019",
"关于",
wx.OK | wx.ICON_INFORMATION)
def updateDisplay(self, mstatus):
"""
Receives data from thread and updates the display
"""
# print('pub display', mstatus)
if mstatus.find("workstart") >= 0:
self.SetStatusText('开始工作,代码不提供中断线程语句,请等待!')
self.startItem.Enable(False)
self.stopItem.Enable(True)
self.exitItem.Enable(False)
if mstatus.find("workdone") >= 0:
self.SetStatusText('完成!')
self.stopItem.Enable(False)
self.startItem.Enable(True)
self.exitItem.Enable(True)
else:
if mstatus.find("查询")>=0:
self.st.SetLabel(mstatus)
else:
self.st2.SetLabel(mstatus)
# if mstatus.find(",") > 0 and mstatus.find("计算") >= 0:
# mdata = mstatus.split(',')
# # 示范 , 实际使用需要传送进度
# # print(int(mdata[0].replace('计算','')))
# g_count = int(mdata[0].replace('计算', ''))
# self.gauge.SetValue(g_count)
def test():
app = wx.App()
frm = MainFrame(None, title='分析工具')
frm.Show()
app.MainLoop()
if __name__ == "__main__":
test()
运行后, 点击 工作-开始。 2个线程开始工作,直到点击工作-结束
来源:https://blog.csdn.net/seakingx/article/details/123713754


猜你喜欢
- MySQL:Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEM1:错误日志大量错误150602 14:40:02 [Warning] Unsafe statement written to the bi
- 有时候在网上办理一些业务时有些需要填写银行卡号码,当胡乱填写时会立即报错,但是并没有发现向后端发送请求,那么这个效果是怎么实现的呢。对于银行
- w3c range range 用来表示用户的选择区域,这块选择区域由两个边界位置界定,而位置则由其容器以及偏移量构成,称作 contain
- 简介有兴趣可以看看: 解释性语言+动态类型语言+强类型语言交互模式:(主要拿来试验,可以试试 ipython)$python>>
- 本文实例讲述了python监控网站运行异常并发送邮件的方法。分享给大家供大家参考。具体如下:这是一个简单的python开发的监控程序,当指定
- 一、在for循环中直接更改列表中元素的值不会起作用:如:l = list(range(10)[::2]) print (l)for n in
- IE的for...in循环存在严重的缺陷,除了性能低下外,有许多属性不可遍历,著名有这三兄弟:constructor ,toString ,
- python使用pyecharts库画地图数据可视化导库中国地图代码结果世界地图代码结果省级地图代码结果地级市地图代码结果导库from py
- 本文介绍了tf.truncated_normal与tf.random_normal的详细用法,分享给大家,具体如下:tf.truncated
- 多线程多线程是个提高程序运行效率的好办法,本来要顺序执行的程序现在可以并行执行,可想而知效率要提高很多。但是多线程也不是能提高所有程序的效率
- ①.页面文件使用正确的编码,gb2312使用ANSI,utf-8使用utf-8; ②.ASP代码中设置正确的CODEPAGE,gb2312使
- 目录一个可能你似曾相识的场景提升办公效率的法宝编码实现谷歌翻译爬虫Python 操作系统剪贴板项目地址妈妈再也不用担心我的英语了。一个可能你
- 关于Jmeter性能测试工具不再过多介绍。如果你要学习软件性能测试,那么多少应该会对它有所耳闻。强烈建议阅读官方文档学习:http://jm
- 在读取https://github.com/Embedding/Chinese-Word-Vectors中的中文词向量时,选择了一个有3G多
- 本文实例讲述了Python 异常的捕获、异常的传递与主动抛出异常操作。分享给大家供大家参考,具体如下:异常的捕获demo.py(异常的捕获)
- 不得不说python的上手非常简单。在网上找了一下,大都是python2的帖子,于是随手写了个python3的。代码非常简单就不解释了,直接
- 匹配括号接下来,我们使用栈解决实际的计算机科学问题。比如我们都写过这样所示的算术表达式, ( 5 + 6 ) ∗ (
- 本文实例为大家分享了Bootstrap导航条实现的具体代码,供大家参考,具体内容如下navbar-header:导航的头部,一般情况下用来放
- 本文实例讲述了python生成IP段的方法。分享给大家供大家参考。具体实现方法如下:#!/usr/local/bin/python#-*-
- 代码案例import pluggy# HookspecMarker 和 HookimplMarker 实质上是一个装饰器带参数的装饰器类,作