【问题标题】:Managing script execution using GUI "buttons" from Tkinter module使用 Tkinter 模块中的 GUI“按钮”管理脚本执行
【发布时间】:2014-08-21 18:48:54
【问题描述】:

有以下脚本:

import sys, Tkinter

def myScript():
    ...

    ...


def runScript():
    while 1:
        myScript()

我想使用 Tkinter 模块中的 GUI“按钮”来管理它

if __name__ == '__main__':
    win = Frame ()
    win.pack ()
    Label(win, text='Choose following action', font=("Helvetica", 16), width=70, height=20).pack(side=TOP)
    Button(win, text='Start script', width=20, height=3, command=runScript).pack(side=LEFT)
    Button(win, text='Stop script', width=20, height=3, command=sys.exit).pack(side=LEFT)
    Button(win, text='Quit', width=15, height=2, command=win.quit).pack(side=RIGHT)
    mainloop()

当我键入“开始脚本”按钮时,我的脚本成功启动并运行(无限循环),但是我想使用“停止脚本”按钮停止执行,我无法执行此操作,因为带有按钮的主窗口不可用(“没有反应”)

我必须改变什么才能正确使用这两个按钮?

【问题讨论】:

  • threading 模块可能有用。

标签: python tkinter


【解决方案1】:

问题在于脚本的执行被认为是阻塞的,因此当它持续运行时,控制永远不会返回到 GUI 以能够继续使用任何外部命令来停止它。要对此进行调整,您将需要使用线程。最好的方法是用threading.Thread 子类化你的脚本方法,并用你的脚本执行重载.run() 方法。这样做看起来像这样:

import threading

class MyScript(threading.Thread):
    def __init__(self):
        super(MyScript, self).__init__()
        self.__stop = threading.Event()

    def stop(self):
        self.__stop.set()

    def stopped(self):
        return self.__stop.isSet()

    def run(self):
        while not self.stopped():
            # Put your script execution here
            print "running"

从那里您可以设置一个全局变量或类变量来跟踪您当前是否有一个线程正在运行(如果您希望用户运行脚本的多个实例,您可能希望以不同的方式执行此操作)和启动方法并停止它。我会推荐一个类变量,你的应用程序本身就是一个类,但这取决于你。

script_thread = None

def startScript():
    global script_thread
    # If we don't already have a running thread, start a new one
    if not script_thread:
        script_thread = MyScript()
        script_thread.start()

def stopScript():
    global script_thread
    # If we have one running, stop it
    if script_thread:
        script_thread.stop()
        script_thread = None

您可以从那里将这些方法绑定到您的按钮。我不确定您是如何设置应用程序结构的(在我看来,您从 Tkinter 导入了所有内容或对 Tkinter.Tk() 实例进行了子类化)。但是,为了执行您建议的操作,您需要使用线程来防止阻塞情况。

【讨论】:

    【解决方案2】:

    使用这个:

    import sys
    from Tkinter import *
    import tkMessageBox as tkmsg
    
    win = None
    
    def myScript():
        pass
    
    def runScript():
        global win
        while 1:
            win.update()
            pass
    
    def btnStop_Click():
        tkmsg.showinfo("Stopped", "Stopped")
        sys.exit
    
    if __name__ == '__main__':
        global win
        win = Frame ()
        win.pack ()
        Label(win, text='Choose following action', font=("Helvetica", 16), width=70, height=20).pack(side=TOP)
        Button(win, text='Start script', width=20, height=3, command=runScript).pack(side=LEFT)
        Button(win, text='Stop script', width=20, height=3, command=btnStop_Click).pack(side=LEFT)
        Button(win, text='Quit', width=15, height=2, command=win.quit).pack(side=RIGHT)
        mainloop()
    

    【讨论】:

    • 这个答案是反模式。您已经运行了一个无限循环,无需创建自己的无限循环调用update
    • 你的解决方案是什么?? @布莱恩
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-23
    • 2011-11-30
    • 1970-01-01
    • 2013-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多