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个线程开始工作,直到点击工作-结束

以上为个人经验,希望能给大家一个参考,也希望大家多多支持Devmax。

WxPython界面利用pubsub如何实现多线程控制的更多相关文章

  1. iOS:核心图像和多线程应用程序

    我试图以最有效的方式运行一些核心图像过滤器.试图避免内存警告和崩溃,这是我在渲染大图像时得到的.我正在看Apple的核心图像编程指南.关于多线程,它说:“每个线程必须创建自己的CIFilter对象.否则,你的应用程序可能会出现意外行为.”这是什么意思?我实际上是试图在后台线程上运行我的过滤器,所以我可以在主线程上运行HUD(见下文).这在coreImage的上下文中是否有意义?

  2. ios – 意外的核心数据多线程违规

    我正在使用苹果的并发核心数据调试器.-com.apple.CoreData.ConcurrencyDebug1有时候我得到__Multithreading_Violation_AllThatIsLeftToUsIsHonor__,即使我几乎肯定线程没有被违反.这是发生异常的代码的一部分(代码是扩展NSManagedobject的协议的一部分):代码在上下文的执行:块中执行.这里是线程信息:和调试器

  3. ios – UIGraphicsBeginImageContextWithOptions和多线程

    我对UIGraphicsBeginImageContextWithOptions和线程有点困惑,因为根据UIKitFunctionReferenceUIGraphicsBeginImageContextWithOptions应该只在主线程上调用.当被调用时,它创建一个基于位图的上下文,可以使用CoreGraphics的函数或者像-drawInRect这样的方法来处理:对于UIImage,-draw

  4. Swift之dispatch_source实现多线程定时关闭功能

    由于在项目中需要用到定时关闭音频功能,本来打算用NSTimer的,可是写起来并不是那么精简好用,所以又在网上找到相关的实例,结合自己项目需要,就写出了如下代码,还请大家指教,废话不多说:

  5. swift 多线程实现

  6. swift_多线程基础_最简单用法GCD, NSOperationQueue, NSThread

    ////ViewController.swift//study1-1//Createdbyadminon15/12/28.//copyright2015年admin.Allrightsreserved.//importUIKitclassViewController:UIViewController{@IBOutletvarmyLable:UILabel?@IBActionfuncclickBut

  7. swift__多线程GCD详解

    有以下*-disPATCH_QUEUE_PRIORITY_HIGH:*-disPATCH_QUEUE_PRIORITY_DEFAULT:多用默认*-disPATCH_QUEUE_PRIORITY_LOW:*-disPATCH_QUEUE_PRIORITY_BACKGROUND:*第二个参数为预留参数,一般为0*/letmyQueue:dispatch_queue_t=dispatch_get_global_queue//用异步的方式运行队列里的任务dispatch_async//-------------

  8. Swift - 多线程实现方式3 - Grand Central DispatchGCD

    dispatchqueue可以是并发的或串行的。dispatch_suspend后,追加到DispatchQueue中尚未执行的任务在此之后停止执行。6//创建并行队列conQueue:dispatch_queue_t=dispatch_queue_create//暂停一个队列dispatch_suspend//继续队列dispatch_resume6,dispatch_once一次执行保证dispatch_once中的代码块在应用程序里面只执行一次,无论是不是多线程。注意,我们不能(直接)取消我们已经提

  9. 【Swift】三种多线程处理方式

    )Threadbtn.frame=CGRectMakeThreadbtn.setTitle//普通状态下的文字Threadbtn.setTitle//触摸状态下的文字letmethod:Selector=methodarr[index!]Threadbtn.addTargetself.view.addSubview;}}overridefuncdidReceiveMemoryWarning(){super.didReceiveMemoryWarning()}//1.NSThread线程functestNS

  10. Swift多线程之GCD

    学自:http://www.jianshu.com/p/2598a4e9c139

随机推荐

  1. 10 个Python中Pip的使用技巧分享

    众所周知,pip 可以安装、更新、卸载 Python 的第三方库,非常方便。本文小编为大家总结了Python中Pip的使用技巧,需要的可以参考一下

  2. python数学建模之三大模型与十大常用算法详情

    这篇文章主要介绍了python数学建模之三大模型与十大常用算法详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感想取得小伙伴可以参考一下

  3. Python爬取奶茶店数据分析哪家最好喝以及性价比

    这篇文章主要介绍了用Python告诉你奶茶哪家最好喝性价比最高,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

  4. 使用pyinstaller打包.exe文件的详细教程

    PyInstaller是一个跨平台的Python应用打包工具,能够把 Python 脚本及其所在的 Python 解释器打包成可执行文件,下面这篇文章主要给大家介绍了关于使用pyinstaller打包.exe文件的相关资料,需要的朋友可以参考下

  5. 基于Python实现射击小游戏的制作

    这篇文章主要介绍了如何利用Python制作一个自己专属的第一人称射击小游戏,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起动手试一试

  6. Python list append方法之给列表追加元素

    这篇文章主要介绍了Python list append方法如何给列表追加元素,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  7. Pytest+Request+Allure+Jenkins实现接口自动化

    这篇文章介绍了Pytest+Request+Allure+Jenkins实现接口自动化的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  8. 利用python实现简单的情感分析实例教程

    商品评论挖掘、电影推荐、股市预测……情感分析大有用武之地,下面这篇文章主要给大家介绍了关于利用python实现简单的情感分析的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

  9. 利用Python上传日志并监控告警的方法详解

    这篇文章将详细为大家介绍如何通过阿里云日志服务搭建一套通过Python上传日志、配置日志告警的监控服务,感兴趣的小伙伴可以了解一下

  10. Pycharm中运行程序在Python console中执行,不是直接Run问题

    这篇文章主要介绍了Pycharm中运行程序在Python console中执行,不是直接Run问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

返回
顶部