【Python】线程threading与GUI窗口tkinter结合应用

Python的threading模块是一个强大的工具,它提供了高级别的线程编程接口。通过这个模块,Python程序员可以在应用程序中实现多线程并发执行。

线程(Thread)是程序执行流的最小单元,被包涵在进程之中,是进程中的一个实体,是被系统独立调度和分派的基本单位。线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。

作者发炎

当我们用tkinter设计开发桌面程序时,不免需要一个或多个线程执行其他任务,例如:显示实时显示时间日期、动态背景、滚动字幕、插件启动与关闭、后台数据监控等......

在本篇文章结合线程threading与窗口tkinter简单设计一个桌面程序显示滚动字幕和显示时间。

运行结果

Thread-1 启动
Thread-2 启动
Thread-2 关闭
Thread-1 关闭

代码示例

"""
    桌面程序
"""

# 通配符 "*"
__all__ = ['MyApp', 'ScrollTitle', 'StatusBar']
__all__.extend(['SCROLL_TITLE', 'TITLE_FLAG', 'STATUS_FLAG'])

# 导入内置模块
import tkinter as tk
from threading import Thread, Lock
import time


# 全局变量
SCROLL_TITLE = ''       # 滚动标题内容
TITLE_FLAG = True       # 滚动标题旗帜
STATUS_FLAG = True      # 状态栏旗帜


class MyApp(tk.Tk):
    """ 继承tk.Tk, 设计我的桌面程序 """
    def __init__(self):
        """ 重写父类的构造方法 """
        # 调用父类的构造方法
        super().__init__()

        """ 开始对我的桌面程序功能进行设计 """

        self.title('我的桌面程序')
        self.geometry('400x300')
        self.status = tk.Label(self, relief='groove')
        self.status.pack(side='bottom', fill='both')
        self.thread_quit = tk.Button(self, text='结束子线程', command=self.quit_thread)
        self.thread_quit.pack(expand=True)


        global SCROLL_TITLE
        SCROLL_TITLE = '欢迎使用我的程序'

        self.title_lock = Lock()      # 创建互斥锁
        # 创建子线程1,执行任务
        self.scroll_title = ScrollTitle(self.title, self.title_lock)
        self.scroll_title.start()     # 启动子线程任务

        self.time_lock = Lock()       # 创建互斥锁
        # 创建子线程2,执行任务
        self.status_Bar = StatusBar(self.status, self.time_lock)
        self.status_Bar.start()       # 启动子线程任务


    def quit_thread(self):
        """ 结束子线程执行任务 """
        global TITLE_FLAG, STATUS_FLAG
        # 结束
        if TITLE_FLAG:
            TITLE_FLAG = False      # 结束滚动标题线程运行
            STATUS_FLAG = False     # 结束状态栏显示时间线程运行
            self.thread_quit.configure(text='开启子线程')
        else:
            TITLE_FLAG = True       # 开启滚动标题线程运行
            STATUS_FLAG = True      # 开启状态栏显示时间线程运行
            self.thread_quit.configure(text='开启子线程')
            # 创建子线程1,执行任务
            self.scroll_title = ScrollTitle(self.title, self.title_lock)
            self.scroll_title.start()  # 启动子线程任务
            # 创建子线程2,执行任务
            self.status_Bar = StatusBar(self.status, self.time_lock)
            self.status_Bar.start()  # 启动子线程任务


class ScrollTitle(Thread):
    """ 继承Thread, 设计滚动标题 """
    def __init__(self, title, lock, name=None):
        """ 重写父类的构造方法 """
        # 调用父类的构造方法
        super().__init__()

        """ 开始对滚动标题进行设计 """

        self.scroll_title = title   # 标题对象
        self.lock = lock            # 互斥锁对象
        if name: self.name = name   # 子线程名字

    def run(self):
        """ 重写父类的run方法 """

        print(self.name, '启动')

        # 执行任务
        while True:
            self.lock.acquire()         # 上锁

            # 修改数据
            for i in range(len(SCROLL_TITLE)):
                self.scroll_title(f'{SCROLL_TITLE[i::]}{" "*3}{SCROLL_TITLE[:i:]}')
                time.sleep(1)
                # 退出条件
                if not TITLE_FLAG:
                    self.lock.release()  # 解锁
                    print(self.name, '关闭')
                    return

            self.lock.release()         # 解锁


class StatusBar(Thread):
    """ 继承Thread, 设计状态栏显示时间 """

    def __init__(self, status, lock, name=None):
        """ 重写父类的构造方法 """
        # 调用父类的构造方法
        super().__init__()

        """ 开始对状态栏显示时间进行设计 """

        self.status = status  # 状态栏对象
        self.lock = lock            # 互斥锁对象
        if name: self.name = name   # 子线程名字

    def run(self):
        """ 重写父类的run方法 """

        print(self.name, '启动')

        # 执行任务
        while True:
            if not STATUS_FLAG: break  # 退出条件

            self.lock.acquire()  # 上锁

            # 状态栏显示时间
            self.status.config(text=f'{time.strftime("%c")}')

            self.lock.release()  # 解锁

        print(self.name, '关闭')


# 代码测试
if __name__ == '__main__':
    ui = MyApp()        # 实例化桌面程序
    ui.mainloop()       # 循环窗口运行
else:
    print(f'导入【{__name__}】')

作者:周华

创作日期:2024/1/17

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/329448.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GitHub图床搭建

1 准备Github账号 如果没有Github账号需要先在官网注册一个账号 2 创建仓库 在github上创建一个仓库,随便一个普通的仓库就行,选择公共仓库 并且配置github仓库的pages,选择默认访问的分支及默认路径 3 github token获取 github token创…

线下安防监控店如何制作小程序商城?开通线上销售渠道

线下安防监控店可以通过制作小程序商城来开通线上销售渠道,为顾客提供更方便快捷的购物体验。下面介绍一种简单的制作小程序商城的方法。 首先,登录【乔拓云】网后台,进入【商城】管理页面。在该页面中,找到并点击【小程序商城】模…

第一次开发基于SpringBoot的Java应用

第一次开发基于SpringBoot的Java应用 一、 方式1:IDEA创建New Project Spring Boot官方文档的Getting Started1、IDEA创建New Project2、Spring Boot官方文档的Getting Started2.1 Creating the POM (实际是,更新pom.xml)2.2 Add…

如何选择适合的乔拓云小程序付费服务

在数字化时代,微信小程序已经成为商家与客户互动的重要平台。乔拓云小程序作为一款便捷的微信小程序,不仅提供免费的基本功能,还为商家提供了多种付费增值服务和广告投放选择,以满足不同需求。本文将为您揭秘乔拓云小程序的费用明…

rabbitmq基础教程(ui,java,springamqp)

概述:安装看我上篇文章Docker安装rabbitmq-CSDN博客 任务一 创建一个队列 这样创建两个队列 在amq.fanout交换机里面发送数据 模拟发送数据 发送消息,发现一下信息: 所以得出理论,消息发送是先到交换机,然后由交换机…

部署配置zabbix监控平台(server端)

目录 引言:明人不说暗话,分享一下部署配置zabbix监控平台的详细过程 1.进入官网 2.进入下载页面选择需要下载的版本信息 (案例zabbix5.0) 划到下面有安装的过程,下面我详细讲解一下这些步骤 3、安装Zabbix存储库 …

Tide Quencher 7.1WS azide,TQ7.1WS N3,适用于多种荧光物质的分析

您好,欢迎来到新研之家 文章关键词:Tide Quencher 7.1WS 叠氮,TQ7.1WS 叠氮,Tide Quencher 7.1WS azide,TQ7.1WS N3,TQ7.1WS azide,Tide Quencher 7.1WS N3 一、基本信息 产品简介&#xff1…

【揭秘AI】穿越时光隧道,探秘AI起源与发展01

算盘 被誉为世界上最古老的计算机之一,是一种手动操作的计算工具,起源于中国。它主要由框、梁和珠子组成,通过移动珠子在档位上的位置来进行加减乘除运算。算盘的发明时间可以追溯到公元前或公元初期,据历史记载,东汉…

vue实现 marquee(走马灯)

样式 代码 <div class"marquee-prompt"><div class"list-prompt" refboxPrompt><span v-for"item in listPrompt" :title"item" class"prompt">{{item}}</span></div> </div>data() {…

【IAP】核心开发流程

最近做了IAP U盘升级模块开发&#xff0c;总结下IAP基本开发流程&#xff0c;不深入讨论原理。 详细原理参考 首先需要知道我们需要把之前的APP区域拆一块出来做BOOT升级程序区域。 以STM32F103为例&#xff0c;0x08000000到0x0807FFFF为FLASH空间&#xff0c;即上图代码区域…

多线程中的run方法和start方法有什么区别?

package org.example;public class MyThread2 extends Thread{/*1&#xff1a;继承Thread2:重写run方法3:创建实例对象并且启动线程* */public static void main(String[] args) {MyThread2 myThread1new MyThread2();myThread1.start();}Overridepublic void run() {for (int …

重置aws上的ssh默认登录端口

aws上的ec2机器&#xff0c;默认ssh的登录都是22&#xff0c;为了防止被黑&#xff0c;记录下修改该默认端口的方法 修改/etc/ssh/sshd_config文件,将Port 22注释去掉在上面的文件中&#xff0c;加入一行&#xff0c;你想要增加的端口号&#xff0c;格式和22一致注意&#xff1…

华清远见作业第二十九天——网络编程(第四天)

思维导图&#xff1a; 基于UDP的TFTP文件传输 代码&#xff1a; #include <a.h> void menu(); int download(int cfd, struct sockaddr_in sin); int up(int cfd, struct sockaddr_in sin); #define SER_PORT 69 #define SER_IP "192.168.125.4" int main(in…

ssh免密登录 ssh公钥分发 ssh密钥生成

在连接服务器时&#xff0c;我们会被要求输入用户名对应的密码&#xff0c;如下&#x1f447;&#xff1a; 如果我们要登录的服务器是常用服务器&#xff0c;那么每次登录输入密码就会比较麻烦。那么如何免密登录呢&#xff1f;那就需要使用到rsa公私钥认证了。 生成rsa密钥…

c++的const和C语言的const的区别

C语言的const 首先&#xff0c;C语言中并不认为const限定的变量是常量&#xff0c;它只是将变量设置为只读的形式了&#xff0c;并不是将其变为了变量。 可以在代码中定义一个const限定的变量&#xff0c;我们知道C语言定义数组只能使用常量&#xff0c;你使用const定义的变量…

Python ❀ 使用代码实现API接口调用详解

文章目录 1. 工具准备1.1. requests代码包1.2. BurpSuite抓包工具 2. 操作过程2.1. 一个简单的请求2.1.1. Burp获取响应2.1.2. 转发获取响应 2.2. 构造GET类型URL参数2.3. 构造请求头部2.4. 构造POST类型payload数据 本文主要讲解常用API接口如何使用python实现。 API&#xff…

使用WAF防御网络上的隐蔽威胁之扫描器

在网络安全领域&#xff0c;扫描器是用于侦察和识别网络系统漏洞的工具。 它们可以帮助网络管理员识别安全漏洞&#xff0c;也可能被攻击者用来寻找攻击目标。 扫描器的基本概念 定义&#xff1a;扫描器是一种自动化工具&#xff0c;用于探测网络和服务器中的漏洞、开放端口、…

图解渠道网关:不只是对接渠道的接口(一)

这是《百图解码支付系统设计与实现》专栏系列文章中的第&#xff08;20&#xff09;篇。点击上方关注&#xff0c;深入了解支付系统的方方面面。 主要讲清楚什么是渠道&#xff0c;有哪些类型的渠道&#xff0c;什么是渠道网关&#xff0c;渠道网关在支付系统中定位、核心功能…

springboot第49集:【思维导图】多线程,常用类与基础API,集合框架,泛型,数据结构源码...

多线程创建方式一&#xff1a;继承Thread类多线程创建方式二&#xff1a;实现Runnable接口jdk5.0新增两种创建多线程的方式 image.png image.png image.png image.png image.png new Thread(new Runnable() {public void run() {for (int i 1; i < 100; i) {if (i % 2 0) …

基于LabVIEW的声音信号采集分析系统开发

摘要&#xff1a;以美国国家仪器(NI)公司开发的LabVIEW虚拟仪器为软件开发平台&#xff0c;设计了一个可以同步实现声音信号采集和分析的多功能模块化软件系统&#xff0e;借助LabVIEW图形化软件相应的声音读取、写入和存储函数实现对声音信号的采集、存储、时域分析和频域分析…
最新文章