【问题标题】:Tkinter Button Acting upTkinter 按钮启动
【发布时间】:2017-12-20 21:04:26
【问题描述】:

我从一个更大的脚本中获得了以下 python 2.7 sn-p 代码。

def RefreshAction():
    execfile("SatTracker.py")

def CloseWindow():
    window.destroy()

button = tk.Frame(window)
button = tk.Button(text='Refresh Data', width=25,command=lambda:[CloseWindow(),RefreshAction()])
button.pack()
window.mainloop()

所以我的整个代码生成了一个带有图像、文本和按钮的 tkinter 窗口。 现在该按钮应该触发关闭 Tkinter 窗口的命令,然后重新运行整个脚本,这很好。当我再次单击刷新按钮时,会发生一些奇怪的事情。窗口不再关闭,但脚本仍会启动,但出现此错误。

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\ProgramData\Anaconda3\envs\python2\lib\lib-tk\Tkinter.py", line 1541, in __call__
    return self.func(*args)
  File "SatTracker.py", line 294, in <lambda>
    button = tk.Button(text='Refresh Data', width=25,command=lambda:[CloseWindow(),RefreshAction()])
  File "C:/Users/Peter Kongstad/Dropbox/Geoscience/2. Masters/7. Semester/Delphini-1 - Software Part/GUI/Programming/SatTracker.py", line 291, in CloseWindow
    window.destroy()
  File "C:\ProgramData\Anaconda3\envs\python2\lib\lib-tk\Tkinter.py", line 1864, in destroy
    self.tk.call('destroy', self._w)
TclError: can't invoke "destroy" command:  application has been destroyed
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\ProgramData\Anaconda3\envs\python2\lib\lib-tk\Tkinter.py", line 1541, in __call__
    return self.func(*args)
  File "C:/Users/Peter Kongstad/Dropbox/Geoscience/2. Masters/7. Semester/Delphini-1 - Software Part/GUI/Programming/SatTracker.py", line 294, in <lambda>
    button = tk.Button(text='Refresh Data', width=25,command=lambda:[CloseWindow(),RefreshAction()])
  File "C:/Users/Peter Kongstad/Dropbox/Geoscience/2. Masters/7. Semester/Delphini-1 - Software Part/GUI/Programming/SatTracker.py", line 288, in RefreshAction
    execfile("SatTracker.py")
  File "SatTracker.py", line 297, in <module>
    window.mainloop()
  File "C:\ProgramData\Anaconda3\envs\python2\lib\lib-tk\Tkinter.py", line 1129, in mainloop
    self.tk.mainloop(n)
KeyboardInterrupt

有效地停止一切。 现在我不一定需要它来关闭旧的 tkinter 窗口,只要当我单击按钮时,脚本会再次运行并开始使用新的更新数据更新当前窗口。

所以无论哪种方式来解决这个问题对我来说都很好。有什么建议吗?

【问题讨论】:

  • 你应该为按钮的command 选项定义一个方法,如果它需要调用多个方法,那么你正在做的事情是不受欢迎的。
  • 我已经更新了。对于那个很抱歉。我是这个 python 编程的真正菜鸟。所以如果我的方法不好,那是因为我不知道更好。如果你能告诉我一个更好的方法。那么请务必这样做 =)
  • 为什么要重启整个脚本?
  • 首先要做的是停止使用lambda。它对某种类型的问题有好处,但这不是那种类型的问题。创建一个适当的函数,以便您可以更轻松地对其进行调试。

标签: python python-2.7 tkinter


【解决方案1】:

基于this answer & comments,以下脚本在按下按钮时重新启动脚本:

import os
import sys

import tkinter as tk

window = tk.Tk()

def restart():
    #CloseWindow()
    RefreshAction()

def RefreshAction():
    os.execl(sys.executable, *([sys.executable]+sys.argv))

def CloseWindow():
    window.destroy()
    #quit()

button = tk.Frame(window)
button = tk.Button(text='Refresh Data', width=25,command=restart)
button.pack()
window.mainloop()

虽然我的用户名中有空格,但它最终会出错。总而言之,除非您有全局变量或其他东西,否则您应该像下面的代码一样:

import tkinter as tk

def restart(root):
    CloseWindow(root)
    RefreshAction()

def RefreshAction():
    main()

def CloseWindow(root):
    root.destroy()

def main():
    window = tk.Tk()
    button = tk.Frame(window)
    button = tk.Button(text='Refresh Data', width=25,
                        command= lambda arg=window: restart(arg))
    button.pack()
    window.mainloop()

main()

您可能还想看看this question & answers 了解如何构建您的 tkinter 程序。我使用的模板与 Bryan 的模板非常相似。

【讨论】:

  • 我不同意遵循 OP 重新启动自己的整个脚本的意图。但我会 +1 以帮助您建议关于 tkinter 程序结构的第二个链接。
【解决方案2】:

不要破坏您的应用程序根窗口。如果你销毁一个窗口,它的子部件就不能再使用了。使用Tk() 创建一个根窗口,然后使用该窗口调用.mainloop()。然后将您想要的窗口设为Toplevel。您可以随时关闭并重新创建它。

另外,我不明白您为什么要再次运行整个脚本。您只想调用重新创建 Toplevel 的代码(可能是因为您没有 Toplevel...)

【讨论】:

  • 我需要重新启动整个程序,因为它从网站获取 TLE 代码,然后将该代码分解为更小的位,然后将其转换为卫星的精确当前纬度和经度坐标。然后将这些长/纬度坐标投影到 3D 地球仪和 2D 地图上,显示其当前位置。然后我针对 Google Chrome 网络驱动程序运行这些坐标,该驱动程序使用这些坐标打开实时天气图和谷歌地球,并根据经度/纬度拍摄图像。最后,所有这些图像都被裁剪、调整大小并巧妙地放入 Tkinter。
  • 您不需要复制您的 cmets。评论答案(通知该用户)并使用“@”后跟要通知的另一个用户的昵称。始终通知原始问题海报。
  • 我知道您需要重新启动该过程,对此毫无疑问。我的意思是(我想你现在已经明白了),重启某些程序并不意味着你重启了一个 GUI。
  • @Kongstad:您的 GUI(演示文稿)应该与您的业务代码(您的流程)分离。 GUI 只是您从中获取输入并更新结果的东西。您甚至可以使用 Python 命令行脚本完成所有操作,并在不构建 GUI 的情况下生成图像文件。如果您愿意,还可以稍后构建一个 GUI 并将其与您之前的代码粘合在一起。所以对于一个 GUI 重启一个进程,这并不意味着 GUI 本身的重启。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-10
  • 1970-01-01
  • 2021-03-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多