首页 > 解决方案 > 如何通过单击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()

如果有人可以通过单击按钮来帮助我开始处理,我将不胜感激,因为我想添加更多按钮,调用更多功能。

标签: pythontkinter

解决方案


线程立即启动的原因是因为它在 中,所以在实例化__init__时被调用。现在你需要一种方法来启动线程,所以我添加了一个名为. 这将创建并启动线程,我们可以从按钮调用此函数。您需要在已经创建的实例中启动线程。当前,您创建了一个新实例,但这将不起作用,因为您想使用已有的实例 ( )。因此,您需要在. 我已经调用它了。然后您可以使用命令启动线程。程序的其余部分保持不变。ThreadedClient
start_thread1
ThreadedClientclientGuiPartclient_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()

推荐阅读