0

So let's say I have a Tkinter GUI that shows a RUN button, a STOP button and a ScrolledText widget. Pressing the RUN button will call a function that includes several log.info() calls. And the text widget is supposed to show those logs. I would like to make those logs showing up real-timely as it occurs, so I tried to run the function as threading, and want it that pressing STOP button would terminate the function. Here is what I have now:

My code:

import tkinter as tk
import logging
import tkinter.scrolledtext as tkst
import threading

class TextHandler(logging.Handler):
    """This class allows you to log to a Tkinter Text or ScrolledText widget"""
    def __init__(self, text):
        # run the regular Handler __init__
        logging.Handler.__init__(self)
        # Store a reference to the Text it will log to
        self.text = text

    def emit(self, record):
        msg = self.format(record)
        def append():
            self.text.configure(state='normal')
            self.text.insert(tk.END, msg + '\n')
            self.text.configure(state='disabled')
            # Autoscroll to the bottom
            self.text.yview(tk.END)

        # This is necessary because we can't modify the Text from other threads
        self.text.after(0, append)

def setup_logger(logger_name, log_file, level=logging.INFO):    

    l = logging.getLogger(logger_name)
    formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')

    if path.exists(log_file) == False:          
        fileHandler = logging.FileHandler(log_file, mode='w')

    else:
        fileHandler = logging.FileHandler(log_file, mode='a')

    fileHandler.setFormatter(formatter) 
    streamHandler = logging.StreamHandler()
    streamHandler.setFormatter(formatter)

    l.setLevel(level)
    l.addHandler(fileHandler)
    l.addHandler(streamHandler)


setup_logger('logA', 'HeresTheLog.log')
log = logging.getLogger('logA')


def threadding():
    app.running = True;
    newthread = threading.Thread(target= function)
    newthread.start()

def function():
    log.info("starts")
    (do things)
    log.info("ends")

def stop():
    app.running = False;

class myApp(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)

        container = tk.Frame(self, width=768, height=576, bg="")
        container.pack(side="top", fill="both", expand = True)
        container.grid_rowconfigure(0, weight=1)     
        container.grid_columnconfigure(0, weight=1)

        self.running = True

        self.frames = {}
        self.show_frame(StartPage)
        self.update_idletasks()

    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()




class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)

        button2 = ttk.Button(self, text="FUNCTION", 
                            command= function
                             )
        button2.pack(pady=10)



        textLog = tkst.ScrolledText(self, state="disabled")
        textLog.pack()

        text_handler = TextHandler(textLog)
        log.addHandler(text_handler)

        stopbutton = ttk.Button(self, text = "STOP!", command = stop)
        stopbutton.pack()




app = myApp()
app.mainloop()

So basically, I am trying to use app.running to control the threading, but this doesn't seem to work. And I know that you can't really just kill a threading. So I am wondering what would be the better way to do this? Maybe using a multiprocess rather than threading so that we could kill it to stop it? Could someone please elaborate on that idea?

Maxim
  • 52,561
  • 27
  • 155
  • 209
Hansong Li
  • 417
  • 2
  • 11
  • 26
  • why do you need threading? Does `(do things)` take a long time? – Bryan Oakley Mar 21 '17 at 03:04
  • Possible duplicate of [Is there any way to kill a Thread in Python?](http://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread-in-python) – CommonSense Mar 21 '17 at 07:40
  • @BryanOakley Yes, do things is gonna do things for about 2 mins, and there are some logging info created during the process, which I want to show as soon as they occur. Also, I would like the user to still have control to the GUI while it's running, so as to make it possible to implement STOP button. – Hansong Li Mar 21 '17 at 18:12

0 Answers0