Python+Tkinter+多线程的实例
Python是一种非常流行的编程语言,支持多种图形界面编程库,其中比较常用的是Tkinter。在Tkinter中,一般情况下GUI程序是单线程的,但可以利用多线程技术来实现一些特定功能的程序设计。本文将详细讲解如何使用Python+Tkinter+多线程编写程序,以实现更加高效的程序设计。
安装Python和Tkinter
在开始学习多线程编程之前, 需要安装Python和Tkinter。Python的下载地址是:https://www.python.org/downloads/,请选择最新版本下载。在Windows环境下,安装完成后,打开命令行窗口,使用pip安装Tkinter模块即可,命令如下:
pip install tkinter
在Linux环境下,使用以下命令安装Tkinter模块:
sudo apt-get install python-tk
多线程介绍
在这里简单介绍一下多线程。在Python中,多线程可以使用threading模块来实现。线程是操作系统能够进行运算调度的最小单位,它被包含在进程中,是比进程更小的能独立运行的基本单位。 通常的方法是定义一个函数来封装需要执行的操作,然后再创建一个线程并将该函数作为参数传递给该线程,等待该线程的执行结束。
案例1:多线程更新进度条
import threading
import tkinter as tk
class ProgressBarThread(threading.Thread):
def __init__(self, progress_var, increment=1, sleep_time=0.1):
threading.Thread.__init__(self)
self.progress_var = progress_var
self.increment = increment
self.sleep_time = sleep_time
def run(self):
for i in range(101):
self.progress_var.set(i)
self.progress_var.update()
if i == 100:
self.progress_var.set(0)
continue
elif i < 70:
self.sleep_time = 0.03
elif i < 90:
self.sleep_time = 0.05
else:
self.sleep_time = 0.1
self.progress_var.increment(self.increment)
time.sleep(self.sleep_time)
class Application(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.grid(sticky=tk.N+tk.S+tk.E+tk.W)
self.progress_var = tk.DoubleVar()
self.progress_var.set(0)
self.progress = tk.ttk.Progressbar(self, orient="horizontal", mode="determinate", variable=self.progress_var)
self.progress.grid(row=0, column=0, padx=5, pady=5, sticky=tk.N+tk.S+tk.E+tk.W)
self.start_btn = tk.Button(self, text="Start", command=self.start_progress)
self.start_btn.grid(row=1, column=0, padx=5, pady=5, sticky=tk.W)
self.stop_btn = tk.Button(self, text="Stop", command=self.stop_progress)
self.stop_btn.grid(row=1, column=0, padx=5, pady=5, sticky=tk.E)
self.progress_thread = None
self.progress_updated = False
def start_progress(self):
if self.progress_thread is not None and self.progress_thread.is_alive():
return
self.progress_thread = ProgressBarThread(self.progress_var, increment=1)
self.progress_thread.start()
def stop_progress(self):
if self.progress_thread is None:
return
self.progress_var.set(0)
self.progress_thread.join()
self.progress_thread = None
if __name__ == '__main__':
root = tk.Tk()
app = Application(master=root)
app.mainloop()
在这个案例中,我们将使用Tkinter的进度条控件来实现一个带有进度条的GUI程序。通过创建一个新的线程来不停的更新进度条,从而避免在主线程中执行这个任务,导致主界面卡顿。
案例2:多线程下载文件
import time
import threading
import tkinter as tk
from tkinter import messagebox
from tkinter.filedialog import askdirectory
import requests
import os
class DownloadThread(threading.Thread):
def __init__(self, url, path):
threading.Thread.__init__(self)
self.url = url
self.path = path
self.download_flag = True
def run(self):
with requests.get(self.url, stream=True) as r:
content_length = int(r.headers.get('Content-Length'))
with open(self.path, 'wb') as f:
for chunk in r.iter_content(chunk_size=1024):
if not self.download_flag:
return
if chunk:
f.write(chunk)
f.flush()
class DownloadApplication(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.grid(sticky=tk.N+tk.S+tk.E+tk.W)
self.url_entry_label = tk.Label(self, text="URL:")
self.url_entry_label.grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
self.url_entry = tk.Entry(self)
self.url_entry.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W+tk.E)
self.browse_button = tk.Button(self, text="Browse", command=self.select_download_path)
self.browse_button.grid(row=1, column=0, padx=5, pady=5, sticky=tk.W)
self.download_path_label = tk.Label(self, text="Download Path:")
self.download_path_label.grid(row=1, column=1, padx=5, pady=5, sticky=tk.W)
self.download_path_entry = tk.Entry(self)
self.download_path_entry.grid(row=2, column=1, padx=5, pady=5, sticky=tk.W+tk.E)
self.start_button = tk.Button(self, text="Start Download", command=self.start_download)
self.start_button.grid(row=3, column=0, padx=5, pady=5, sticky=tk.W)
self.stop_button = tk.Button(self, text="Stop Download", command=self.stop_download, state=tk.DISABLED)
self.stop_button.grid(row=3, column=1, padx=5, pady=5, sticky=tk.E)
self.download_thread = None
def select_download_path(self):
download_dir = askdirectory(title="Select Download Path")
self.download_path_entry.delete(0, tk.END)
self.download_path_entry.insert(tk.END, download_dir)
def start_download(self):
if not self.url_entry.get():
messagebox.showinfo("Error", "Please input your url")
return
if not self.download_path_entry.get():
messagebox.showinfo("Error", "Please select download path")
return
if self.download_thread is not None and self.download_thread.is_alive():
messagebox.showinfo("Error", "Download task is already in progress")
return
url = self.url_entry.get()
download_path = os.path.join(self.download_path_entry.get(), url.split("/")[-1])
self.download_thread = DownloadThread(url, download_path)
self.download_thread.start()
self.start_button["state"] = tk.DISABLED
self.stop_button["state"] = tk.NORMAL
def stop_download(self):
if self.download_thread is None:
return
self.download_thread.download_flag = False
self.start_button["state"] = tk.NORMAL
self.stop_button["state"] = tk.DISABLED
if __name__ == '__main__':
root = tk.Tk()
app = DownloadApplication(master=root)
app.mainloop()
在这个案例中,我们将使用Tkinter创建一个GUI程序,可以输入URL,并且选择下载路径。同时在下载过程中,启动新的线程来执行下载操作,主线程负责更新进度条和响应“停止下载”操作。使用多线程可同时实现文件下载和下载进度的更新,而不会导致主界面卡顿。
以上两个案例给出的是Python+Tkinter+多线程实践的经典示例,想要掌握更多关于这方面的知识,需要对Python和Tkinter有更加深入全面的了解。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python+Tkinter+多线程的实例 - Python技术站