【问题标题】:Tkinter threadingTkinter 线程
【发布时间】:2013-06-18 11:05:08
【问题描述】:

尽管看到很多关于这个话题的问题,但我找不到合适的答案来解决我的困惑。我是 Python 的初学者,它是我的第一语言。我正在尝试创建一个对话框,在打开该框时自动运行测试。测试完成后,我希望打开另一个对话框,说明测试已完成。测试功能正常且运行正常。但是,由于辅助对话框正在调用 Tk() 的第二个实例,因此它不会打开。

我的问题:如何更改我的代码以允许在完成测试时打开辅助对话框?

obj_rcs 是正在运行的测试。 obj_config 是辅助对话框。

我的代码:

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()

【问题讨论】:

    标签: python multithreading tkinter


    【解决方案1】:

    看起来问题在于,当您调用其他模块中的函数时,您正在创建另一个 Tk 元素,因为您没有将创建的元素传递给 complete() 函数。因此,它应该接受一个master 参数,然后在另一个模块中使用它,然后避免多个根 Tk 元素。

    此外,您正在使用多个几何管理器(place 和 pack)。您应该在同一窗口中只使用一个以避免意外行为。此外,这个方法总是返回None,所以像plabel = ...这样的赋值是没有用的——不仅因为它存储了None,还因为它可能会产生误导。


    编辑:我添加了对您的代码的修改,以便您可以大致了解如何与生成线程进行通信。我没有测试过,但至少它可以作为一个参考,以获得大致的想法。

    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()
    

    【讨论】:

    • 小心你的术语。 “同一窗口”含糊不清。 “窗口”是什么意思?一个小部件?顶层窗口?您不应该将它们混合在同一个容器小部件中,但将它们混合在同一个应用程序中是可以的。如果您使用“窗口”来表示整个窗口,包括其所有子小部件,则将它们混合在同一个窗口中很好。如果你真的指的是Tk 或Toplevel 的同一个实例,那么混合它们是不好的。
    • @BryanOakley 我使用了“窗口”这个词,因为该术语在文档中也用于指代根窗口和顶层小部件:pythonware.com/library/tkinter/introduction/…, effbot.org/tkinterbook/wm.htm
    • 如何为我的辅助对话框创建主参数?
    • @GeorgeLonngren 这取决于您如何创建对话框:如果它是 Toplevel 小部件,则将 master 作为构造函数的第一个参数传递。如果它是对 tkMessageBox 函数的调用,则不需要它,但问题的原因是不同的。
    • @A. Rodas 我已将要引用的类添加到我的代码中。我已经知道它现在甚至没有功能,因为我试图在某些地方切换某些值。请原谅我缺乏理解,但除非我做错了,否则传递主论点对我不起作用。
    猜你喜欢
    • 2014-12-29
    • 2014-07-30
    • 1970-01-01
    • 1970-01-01
    • 2018-06-26
    • 2013-10-14
    • 1970-01-01
    相关资源
    最近更新 更多