python - 如何通过单击python中的按钮开始处理
问题描述
我最近开发了一个 python 程序,它可以读取 csv 文件并在处理它们之后返回包含图形的 pdf。但是,如果 csv 文件很大,程序会冻结,直到处理完成。使用这种方法:Link,程序不再冻结,而是自动启动而无需按任何按钮。
这是代码:
try:
import Tkinter as tk, time, threading, random, Queue as queue
except ModuleNotFoundError: # Python 3
import tkinter as tk, time, threading, random, queue
class GuiPart(object):
def __init__(self, master, queue):
self.queue = queue
self.button1 = tk.Button(master, text="Command", padx=10,
pady=5, fg="white", bg="#263D42", command=ThreadedClient.worker_thread1)
self.button1.pack()
def processIncoming(self):
while self.queue.qsize():
pass
class ThreadedClient(object):
"""
Launch the main part of the GUI and the worker thread. periodic_call()
and end_application() could reside in the GUI part, but putting them
here means that you have all the thread controls in a single place.
"""
def __init__(self, master):
"""
Start the GUI and the asynchronous threads. We are in the main
(original) thread of the application, which will later be used by
the GUI as well. We spawn a new thread for the worker (I/O).
"""
self.master = master
# Create the queue
self.queue = queue.Queue()
# Set up the GUI part
self.gui = GuiPart(master, self.queue)
# Set up the thread to do asynchronous I/O
# More threads can also be created and used, if necessary
self.running = True
self.thread1 = threading.Thread(target=self.worker_thread1)
self.thread1.start()
# Start the periodic call in the GUI to check the queue
self.periodic_call()
def periodic_call(self):
""" Check every 200 ms if there is something new in the queue. """
self.master.after(200, self.periodic_call)
self.gui.processIncoming()
if not self.running:
# This is the brutal stop of the system. You may want to do
# some cleanup before actually shutting it down.
import sys
sys.exit(1)
def worker_thread1(self):
"""
This is where we handle the asynchronous I/O. For example, it may be
a 'select()'. One important thing to remember is that the thread has
to yield control pretty regularly, be it by select or otherwise.
"""
while self.running:
# To simulate asynchronous I/O, create a random number at random
# intervals. Replace the following two lines with the real thing.
time.sleep(rand.random() * 1.5)
filenames = filedialog.askopenfilenames(initialdir="/", title="Select File", filetypes = (("comma separated file","*.csv"), ("all files", "*.*"))) #ask user to select the file
""" based on the data from csv file I am using matplotlib to draw some graphs and then I export them as pdf """
def end_application(self):
self.running = False # Stops worker_thread1 (invoked by "Done" button).
rand = random.Random()
root = tk.Tk()
client = ThreadedClient(root)
root.mainloop()
如果有人可以通过单击按钮来帮助我开始处理,我将不胜感激,因为我想添加更多按钮,调用更多功能。
解决方案
线程立即启动的原因是因为它在 中,所以在实例化__init__
时被调用。现在你需要一种方法来启动线程,所以我添加了一个名为. 这将创建并启动线程,我们可以从按钮调用此函数。您需要在已经创建的实例中启动线程。当前,您创建了一个新实例,但这将不起作用,因为您想使用已有的实例 ( )。因此,您需要在. 我已经调用它了。然后您可以使用命令启动线程。程序的其余部分保持不变。ThreadedClient
start_thread1
ThreadedClient
client
GuiPart
client_instance
client_instance.start_thread1
class GuiPart(object):
def __init__(self, master, queue, client_instance):
self.queue = queue
self.button1 = tk.Button(master, text="Command", padx=10,
pady=5, fg="white", bg="#263D42", command=client_instance.start_thread1)
self.button1.pack()
def processIncoming(self):
while self.queue.qsize():
pass
class ThreadedClient(object):
"""
Launch the main part of the GUI and the worker thread. periodic_call()
and end_application() could reside in the GUI part, but putting them
here means that you have all the thread controls in a single place.
"""
def __init__(self, master):
"""
Start the GUI and the asynchronous threads. We are in the main
(original) thread of the application, which will later be used by
the GUI as well. We spawn a new thread for the worker (I/O).
"""
self.master = master
# Create the queue
self.queue = queue.Queue()
self.running = True
# Set up the GUI part
self.gui = GuiPart(master, self.queue, self)
# Start the periodic call in the GUI to check the queue
self.periodic_call()
def start_thread1(self):
# Set up the thread to do asynchronous I/O
# More threads can also be created and used, if necessary
thread1 = threading.Thread(target=self.worker_thread1)
thread1.start()
推荐阅读
- mysql - 触发 if else with between
- android - 我想我做了一些 setstate 不能正常工作的事情
- html - 为什么我的代码中出现错误“JSX 元素 'div' 没有相应的结束标记”
- javascript - 如何在js中的同一个寡妇中打开html文件中的html文件
- c# - 如何通过来自Web api项目目录的角度的URL显示图像
- python - 无法使用 **kwargs 传递对象
- postman - 如何在 Postman 中测试带有多个参数的 Nest.js GET 请求?
- vba - 由于在 Office 365 中保存文件在 2013 版中运行宏时出错
- python - 如何从 3D 数组中删除偶数元素
- c++ - Boost::interprocess消息队列与windows兼容?