解决python tkinter界面卡死的问题

yipeiwu_com5年前Python基础

如果点击按钮,运行了一个比较耗时的操作,那么界面会卡死。

import tkinter as tk
import time
 
def onclick(text, i):
  time.sleep(3)
  text.insert(tk.END, '按了第{}个按钮\n'.format(i))
 
  
  
root = tk.Tk()
 
text = tk.Text(root)
text.pack()
 
tk.Button(root, text='按钮1', command=lambda :onclick(text,1)).pack()
tk.Button(root, text='按钮2', command=lambda :onclick(text,2)).pack()
 
root.mainloop()

解决办法:

方式一、直接开线程

import tkinter as tk
import time
import threading
 
 
songs = ['爱情买卖','朋友','回家过年','好日子']
movies = ['阿凡达','猩球崛起']
 
def music(songs):
  global text # 故意的,注意与movie的区别
  for s in songs:
    text.insert(tk.END, "听歌曲:%s \t-- %s\n" %(s, time.ctime()))
    time.sleep(3)
 
def movie(movies, text):
  for m in movies:
    text.insert(tk.END, "看电影:%s \t-- %s\n" %(m, time.ctime()))
    time.sleep(5)
 
  
def thread_it(func, *args):
  '''将函数打包进线程'''
  # 创建
  t = threading.Thread(target=func, args=args) 
  # 守护 !!!
  t.setDaemon(True) 
  # 启动
  t.start()
  # 阻塞--卡死界面!
  # t.join()
 
 
root = tk.Tk()
 
text = tk.Text(root)
text.pack()
 
tk.Button(root, text='音乐', command=lambda :thread_it(music, songs)).pack()
tk.Button(root, text='电影', command=lambda :thread_it(movie, movies, text)).pack()
 
root.mainloop()

方式二、继承 threading.Thread 类

import tkinter as tk
import time
import threading
 
 
songs = ['爱情买卖','朋友','回家过年','好日子']
movies = ['阿凡达','猩球崛起']
 
def music(songs):
  global text # 故意的,注意与movie的区别
  for s in songs:
    text.insert(tk.END, "听歌曲:%s \t-- %s\n" %(s, time.ctime()))
    time.sleep(3)
 
def movie(movies, text):
  for m in movies:
    text.insert(tk.END, "看电影:%s \t-- %s\n" %(m, time.ctime()))
    time.sleep(5)
 
class MyThread(threading.Thread):
  def __init__(self, func, *args):
    super().__init__()
    
    self.func = func
    self.args = args
    
    self.setDaemon(True)
    self.start()  # 在这里开始
    
  def run(self):
    self.func(*self.args)
  
 
root = tk.Tk()
 
text = tk.Text(root)
text.pack()
 
tk.Button(root, text='音乐', command=lambda :MyThread(music, songs)).pack()
tk.Button(root, text='电影', command=lambda :MyThread(movie, movies, text)).pack()
 
root.mainloop()

三、或者,搞一个界面类:

import tkinter as tk
import time
import threading
 
songs = ['爱情买卖','朋友','回家过年','好日子'] 
films = ['阿凡达','猩球崛起']
 
 
class Application(tk.Tk):
def __init__(self):
    super().__init__()
    
    self.createUI()
 
  # 生成界面
  def createUI(self):
    self.text = tk.Text(self)
    self.text.pack()
 
    tk.Button(self, text='音乐', command=lambda :self.thread_it(self.music, songs)).pack(expand=True, side=tk.RIGHT) # 注意lambda语句的作用!
    tk.Button(self, text='电影', command=lambda :self.thread_it(self.movie, films)).pack(expand=True, side=tk.LEFT)
    
 
  # 逻辑:听音乐
  def music(self, songs):
    for x in songs:
      self.text.insert(tk.END, "听歌曲:%s \t-- %s\n" %(x, time.ctime()))
      print("听歌曲:%s \t-- %s" %(x, time.ctime()))
      time.sleep(3)
 
  # 逻辑:看电影
  def movie(self, films):
    for x in films:
      self.text.insert(tk.END, "看电影:%s \t-- %s\n" %(x, time.ctime()))
      print("看电影:%s \t-- %s" %(x, time.ctime()))
      time.sleep(5)
 
  # 打包进线程(耗时的操作)
  @staticmethod
  def thread_it(func, *args):
    t = threading.Thread(target=func, args=args) 
    t.setDaemon(True)  # 守护--就算主界面关闭,线程也会留守后台运行(不对!)
    t.start()      # 启动
    # t.join()     # 阻塞--会卡死界面!
    
    
app = Application()
app.mainloop()

以上这篇解决python tkinter界面卡死的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持【听图阁-专注于Python设计】。

相关文章

Python登录注册验证功能实现

简介 本次项目登录注册验证是对之前学习知识点的加深学习,这次项目的练习的知识点有函数、判断语句、循环语句、文件操作等。 项目流程 运行代码之后,输出登录或者注册选项。 当选择登录之后...

python如何保证输入键入数字的方法

要求:python写一个要求用户输入数字,如果不是数字就一直循环要求输入,直到输入数字为止的代码 错误打开方式: while True: ten=input('Enter a n...

python实现多线程端口扫描

一个简易的TCP端口扫描器,使用python3实现。 需求:扫描目标网站开放哪些端口号,将所有开放的端口号输出。 分析:使用socket连接,如果连接成功,认为端口开放,如果连接失败,认...

通过PHP与Python代码对比的语法差异详解

一、背景 人工智能这几年一直都比较火,笔者一直想去学习一番;因为一直是从事PHP开发工作,对于Python接触并不算多,总是在关键时候面临着基础不牢,地动山摇的尴尬,比如在遇到稍微深入...

关于pycharm中pip版本10.0无法使用的解决办法

关于pycharm中pip版本10.0无法使用的解决办法

一、背景: 近期在利用 pycharm 安装第三方库时会提示 pip 不是最新版本, 因此对 pip 进行更新,但是生成最新版本之后, pip 中由于缺少 main 函...