用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')