【问题标题】:Make python wait for setting of variable through tkinter让python等待通过tkinter设置变量
【发布时间】:2020-03-19 23:05:34
【问题描述】:

我在使用 tkinter 时遇到了这个问题,我想在其中设置文档的来源,以便我的代码可以使用搜索按钮和 askopenfilename 在 python 中处理文件。

这是我的代码片段。

...
from tkinter import *
from tkinter import filedialog

root = Tk()
root.title("Alpha")
root.iconbitmap('images\alpha.ico')


def search():
    global location
    root.filename = filedialog.askopenfilename(initialdir="/", title="Select A File",
                                               filetypes=(("txt files", "*.txt"), ("All Files", "*.*")))
    location = root.filename

open_button = Button(root, text="Open File", command=search).pack()


input_txt = open(location, "r", encoding="utf8")
...
root.mainloop()

问题:当我运行程序时,窗口会打开片刻,我立即收到input_txt 变量中的location 未定义的错误,我完全理解。我想我的 python 代码并没有等我按下程序窗口中的按钮并搜索我的文件,因此可以定义 location。在尝试定义input_txt之前,如何让python等待open()返回location的值?

我试过了

import time
...
location = ''
open_button = Button(root, text="Open File", command=open).pack()
while not location:
    time.sleep(0.1)

然而,这会导致程序冻结,我知道睡眠在这里不是最好的选择。 有什么建议吗?

【问题讨论】:

  • 我不完全明白你在这里想要达到的目标。我知道您想根据用户的 GUI 输入打开文件,但是在您的第一个代码 sn-p 中,我不明白您为什么要定义全局变量。你也可以在你的函数中操作输入文件。
  • 我认为您不了解 GUI 事件处理和编程。请参阅@Bryan Oakley 对Tkinter — executing functions over time 的回答。

标签: python button tkinter block wait


【解决方案1】:

关于您的问题

就像boomkin 建议的那样,我建议将input_txt = open(location, ...) 行移到您的search 函数中。这样,程序只会在您按下按钮并定义 location 后尝试从 location 打开。

如果还有其他事情发生,您可以创建另一个函数并调用它:

def file_handling(location):
    input_txt = open(location, "r", encoding="utf8")
    ... #anything using input_txt

def search():
    root.filename = filedialog.askopenfilename(initialdir="/", title="Select A File",
                                               filetypes=(("txt files", "*.txt"), ("All Files", "*.*")))
    file_handling(root.filename)

open_button = Button(root, text="Open File", command=search)
open_button.pack()
...
root.mainloop()

问题是 Tkinter 对象在你到达主循环之前不会做任何事情——但是一旦你进入主循环,你就不能回去填充任何东西。所以你想做的一切都必须是与某种输入相关联:例如按下按钮(或击键或鼠标悬停)。

在这种情况下,你想设置location,但你必须等到你调用 mainloop 并且按钮开始接受输入。但是到那时,您已经通过了需要location 并且无法返回的线路。这就是为什么我建议从search 函数调用input_txt 行的原因——因为在你已经获得位置之前它不会被调用。

这有点啰嗦,但我希望它能阐明问题。

作为旁注

我还建议您单独声明和打包小部件。也就是说,改变这个:

open_button = Button(root, text="Open File", command=search).pack()

到这里:

open_button = Button(root, text="Open File", command=search)
open_button.pack()

否则,您最终将存储pack() 的值(即None)而不是存储您的小部件(Button 对象)。

【讨论】:

  • Tkinter 对象在主循环之前不是空闲的,主循环是让它们显示/绘制并停留在屏幕上的无限循环,直到终止。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多