多线程解决程序运行时tkinter界面卡死的问题

3,170 阅读2分钟

blog.csdn.net/BBJG_001/ar…

用tkinter写了个窗口界面来 Python+FFmpeg音视频格式转换 ,点击执行之后,完蛋,界面卡死了。

因为调用的后台程序执行时间过长,tkinter是通过不停的刷新页面来进行显示的,这个程序一调用,tkinter就不能刷新了,界面就卡死了。

欸,这时候就想起了多线程,一个线程去后台执行程序,一个线程用来在前面刷新显示。

就去搜了一下,果然跟我想的一样~

# 点击提交执行的功能
def executeit():
    hint.set('converting . . .')
    convert(pathin.get(), pathout.get(), aimf.get())
    hint.set('convert finished')

# 创建线程执行程序
def thread_it(func, *args):		# 传入函数名和参数
    # 创建线程
    t = threading.Thread(target=func, args=args)
    # 守护线程
    t.setDaemon(True)
    # 启动
    t.start()
    
# 提交按钮
# tk.Button(window, text='  提 交  ', command=executeit).place(x=200, y=190)	# 普通执行
tk.Button(window, text='  提 交  ', command=lambda:thread_it(executeit)).place(x=200, y=190)	# 通过另外线程执行

完整代码如下

import tkinter as tk
from tkinter.filedialog import *
from convert import convert		# 导入我自己写的方法
# 在pycharm的编译器中这种方式无法通过,在用pyinstaller封装是是能识别的,并且pyinstaller无法识别从工程根目录开始一层层import的方式
# 注:上述写法是从conver.py中导入conver方法
import threading

# 点击“选择文件”按钮调用该功能
def selectFilePath():
    path_ = askopenfilename(title='选择文件')
    pathin.set(path_)
    print(pathin.get())

# 点击“选择文件夹”调用该功能
def selectDirecPath():
    path_ = askdirectory(title='选择文件夹')
    # path_ = askopenfilename(title='选择文件')
    pathout.set(path_)
    print(path_)

# 点击提交执行的功能
def executeit():
    hint.set('converting . . .')
    convert(pathin.get(), pathout.get(), aimf.get())
    hint.set('convert finished')

def thread_it(func, *args):
    # 创建线程
    t = threading.Thread(target=func, args=args)
    # 守护线程
    t.setDaemon(True)
    # 启动
    t.start()

# 生成窗口
window = tk.Tk()
window.title('格式转换')
window.geometry('450x300')

# 格式转换label
tk.Label(window, text='格式转换').place(x=200, y=10)  # x是从左向右的偏移,y是从上向下的偏移

# 输入文件一行
pathin = tk.StringVar()     # 定义变量
tk.Label(window, text='输入文件:').place(x=50, y=50)
entry_pathin = tk.Entry(window, textvariable=pathin).place(x=160, y=50)     # 输入框
btn_pathin = tk.Button(window, text='选择文件', command=selectFilePath).place(x=340, y=45)  # 按钮

# 输出文件的一行
pathout = tk.StringVar()
tk.Label(window, text='输出位置:').place(x=50, y=100)  # 从左偏,从上偏
tk.Entry(window, textvariable=pathout).place(x=160, y=100)
tk.Button(window, text='选择文件夹', command=selectDirecPath).place(x=335, y=95)

# 目标格式的一行
aimf = tk.StringVar()
tk.Label(window, text='目标格式:').place(x=50, y=150)  # 从左偏,从上偏
tk.Entry(window, textvariable=aimf).place(x=160, y=150)

# 提交按钮
# tk.Button(window, text='  提 交  ', command=executeit).place(x=200, y=190)
tk.Button(window, text='  提 交  ', command=lambda:thread_it(executeit)).place(x=200, y=190)

# 提示区域
hint = tk.StringVar()
hint.set('')
tk.Label(window, textvariable=hint).place(x=190, y=240)

# 不停的刷新显示
window.mainloop()


上面的代码从我自己写的convert.py导入了convert这个函数

import os

def convert(pin, pout, aim):
    fname = pin.split('/')[-1].split('.')[0]
    print(fname)
    cmd = 'ffmpeg -i ' + pin + ' ' + pout+'/'+fname+'.'+aim
    print('converting. . .')
    # os.popen()命令会转为后台运行,先完成后面的命令的执行
    # os.popen(cmd)
    os.system(cmd)
    print('convert finished')