user2483250
user2483250

Reputation:

Tkinter threading

Despite seeing many questions being asked about this very topic, I can not find a suitable answer for my quandary. I am a beginner at Python and it is my first language. I am trying to create a dialog box that runs a test automatically on opening the box. When the test finishes, I want another dialog box to open which states the test is complete. The test is functional and runs properly. However, since the secondary dialog is calling a second instance of Tk(), it will not open.

My Question: How can I change my code in order to allow the secondary dialog box to open on completion of my test?

obj_rcs is the test being run. obj_config is the secondary dialog box.

My Code:

enter code here
from configcomplete_slice import complete
from slice_setup import SLICE_SETUP
import Tkinter
import threading
import Queue

class GuiPart:

    def __init__(self, master, queue):
        self.queue = queue
        master.geometry("300x100+400+250")
        master.title("RSAM BCT")
        Tkinter.Label(master, text= "REDCOM SLICE", fg="red").pack()
        Tkinter.Label(master, text= "BCT - Basic Configuration Test",    
        fg= "red").pack()
        Tkinter.Label(master, text= "Please wait...", fg= "black").pack()
        Tkinter.Label(master, text= "Estimated time: 3 min 6 sec", 
        fg= "black").pack()


    def processIncoming(self):
        while self.queue.qsize():
            try:
                msg = self.queue.get(0)
                print msg
            except Queue.Empty:
                pass

class ThreadedClient:

    def __init__(self, master):
        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
        self.running = 1
        self.thread1 = threading.Thread(target = self.workerThread1)
        self.thread1.start()
        self.periodicCall()

    def periodicCall(self):
        self.gui.processIncoming()
        if not self.running:
            import sys
            sys.exit(1)
        self.master.after(100, self.periodicCall)

    def workerThread1(self):
        while self.running:
            obj_rcs = SLICE_SETUP()
            obj_com = complete()

            obj_rcs.SLICE()
            obj_com.config()

root = Tkinter.Tk()
client = ThreadedClient(root)
root.mainloop()

class complete:

    def config(self):
        Tkinter.geometry("400x300+400+250")
        Tkinter.title("RSAM BCT")
        Tkinter.Label(master, text= "REDCOME SLICE", fg="red").pack()
        Tkinter.Label(master, text= "BCT - Basic Configuration Test", fg= "red").pack()
        Tkinter.Label(master, text= "Configuration Complete!", fg= "dark green").pack()
        Tkinter.Label(master, text= "Trunk 1: Port 1: Phone 1: 760-450-4500", 
        fg= "black").pack()
        Tkinter.Label(master, text= "Trunk 1: Port 2: Phone 2: 760-450-4501", 
        fg= "black").pack()
        Tkinter.Button(master, text = "    Exit    ", 
        command = Tkinter.destroy).pack()

Upvotes: 1

Views: 3822

Answers (1)

A. Rodas
A. Rodas

Reputation: 20679

It looks like the problem is that you are creating another Tk element when you call the functions in the other modules, since you don't pass the one you create to the complete() function. Thus, it should accept a master argument, and then use it in the other module and then avoid multiple root Tk elements.

Besides, you are using more than one geometry manager (place and pack). You should use only one in the same window to avoid unexpected behaviour. Besides, this methods always return None, so the assignments like plabel = ... are useless - not only because it stores None but also because it may be misleading.


EDIT: I've added a modification of your code so you can have an overview of how to communicate with the spawn thread. I have not tested it, but at least it can be a reference to get the general idea.

from slice_setup import SLICE_SETUP
import Tkinter as tk
import threading
import Queue

class GuiPart:
    def __init__(self, master, queue):
        self.queue = queue
        self.master = master
        self.master.geometry("300x100+400+250")
        self.master.title("RSAM BCT")
        tk.Label(master, text="REDCOM SLICE", fg="red").pack()
        tk.Label(master, text="BCT - Basic Configuration Test", fg= "red").pack()
        tk.Label(master, text="Please wait...", fg= "black").pack()
        tk.Label(master, text="Estimated time: 3 min 6 sec", fg= "black").pack()

    def processIncoming(self):
        while self.queue.qsize():
            try:
                text = self.queue.get(0)
                Complete(self.master, text)
            except Queue.Empty:
                pass

class ThreadedClient:
    def __init__(self, master):
        self.master = master
        self.queue = Queue.Queue()
        self.gui = GuiPart(master, self.queue)
        self.running = True
        self.thread = threading.Thread(target=self.workerThread1)
        self.thread.start()
        self.periodicCall()

    def periodicCall(self):
        self.gui.processIncoming()
        if not self.running:
            return
        self.master.after(100, self.periodicCall)

    def workerThread1(self):
        obj_rcs = SLICE_SETUP()
        obj_rcs.SLICE()
        self.queue.put("Configuration Complete!")
        self.running = False

class Complete(tk.Toplevel):
    def __init__(self, master=None, completetext=""):
        tk.Toplevel.__init__(self, master)
        self.geometry("400x300+400+250")
        self.title("RSAM BCT")
        tk.Label(self, text="REDCOME SLICE", fg="red").pack()
        tk.Label(self, text="BCT - Basic Configuration Test", fg="red").pack()
        tk.Label(self, text=completetext, fg="dark green").pack()
        tk.Label(self, text="Trunk 1: Port 1: Phone 1: 760-450-4500", fg="black").pack()
        tk.Label(self, text="Trunk 1: Port 2: Phone 2: 760-450-4501", fg="black").pack()
        tk.Button(self, text="    Exit    ", command=self.destroy).pack()


if __name__ == "__main__":
    root = Tkinter.Tk()
    client = ThreadedClient(root)
    root.mainloop()

Upvotes: 2

Related Questions