Заставьте python дождаться установки переменной через tkinter - PullRequest
0 голосов
/ 20 марта 2020

Я сталкиваюсь с этой проблемой с tkinter, где я хочу установить источник документа, чтобы мой код мог работать с файлом в python, используя кнопку поиска и askopenfilename.

здесь есть фрагмент моего кода.

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

Проблема: Когда я запускаю программу, окно открывается на короткое время, и я сразу получаю сообщение об ошибке, что location в переменной input_txt не определено, что я полностью понимаю. Я думаю, мой код python не ждет, когда я нажму кнопку в окне программы и найду свой файл, чтобы можно было определить location. Как я могу заставить python ждать, пока open() вернет значение для location, прежде чем пытаться определить input_txt?

Я пытался с

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

, однако это вызывает программа заморозки и я знаю, что сон не самый лучший вариант здесь. Есть предложения?

1 Ответ

0 голосов
/ 20 марта 2020

Относительно вашего вопроса

Как подсказывает Бумкин, я бы посоветовал переместить строку 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 ничего не делают, пока вы не достигнете mainl oop - но как только вы окажетесь в mainl oop, вы не сможете go назад и заполните все. Итак, все, что вы хотите сделать, должно быть привязано к некоторому типу ввода: например, к нажатию кнопки (или нажатию клавиши, или наведению курсора).

В этом случае вы хотите установить location, но вам нужно подождать, пока вы не вызовете mainl oop и кнопка не начнет вводить данные. Но к тому времени вы прошли линию, которая нуждается в location и не может go назад. Вот почему я предлагаю вызывать строку input_txt из функции search - потому что она не будет вызываться до тех пор, пока вы не получите местоположение.

Это немного скучно, но я надеюсь, это осветило проблему.

В качестве идентификатора

Я бы также рекомендовал вам объявлять и упаковывать свои виджеты отдельно. То есть, измените это:

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

...