2014-12-28 6 views
2

Я пишу программу для своего класса, которая позволяет вам создавать рецепт, сохранять его и редактировать его даже после закрытия программы. Для этого вам явно нужен текстовый файл.Как добавить опции в OptionMenu из текстового файла

Я использую OptionMenu (Tkinter, Python 3.3.3), но я не могу понять, как его обновить, чтобы иметь первый вариант в списке, который я сделал в своем текстовом файле. Итак, как мне это сделать?

Мой код таким образом:

########################################### 
########################################### 
### RECIPE BOOK TASK ##### By 18166 ####### 
########################################### 
########################################### 

from tkinter import * 


def script(): 

    #### MAIN #### 

    fake_window = Tk() 
    new_recipe_window = fake_window 
    start_window = fake_window 
    start_window.title("Recipe Book Task") 

    #### MAIN #### 



    ## DATA FILE ## 

    global datafile 
    datafile = open("StoredRecipes.txt", "a+") 

    ## DATA FILE ## 



    ### Functions ### 

    def close (x):                ## Close Original Window ## 
     global start_window 
     global new_recipe_window 
     (x).withdraw() 

    def new_recipe(): 
     new_recipe_window = Tk()            ## Making new window ## 
     new_recipe_window.title("New Recipe") 
     close(start_window) 

     recipe_name_label = Label(new_recipe_window, text="Recipe Name: ")  ## Making new recipe label ## 
     recipe_name_label.grid(row=0, column=0) 
     recipe_name_box = Entry(new_recipe_window)        ## Making new recipe entry ## 
     recipe_name_box.grid(row=0, column=1) 

     num_people_label = Label(new_recipe_window, text="Number of people: ") ## Making number of people label ## 
     num_people_label.grid(row=1, column=0) 
     num_people_box = Entry(new_recipe_window)        ## Making number of people entry ## 
     num_people_box.grid(row=1, column=1) 

     item_label = Label(new_recipe_window, text="Items: ")     ## Making item label ## 
     item_label.grid(row=2, column=0) 
     item_box = Entry(new_recipe_window)          ## Making item entry ## 
     item_box.grid(row=2, column=1) 

     quantity_label = Label(new_recipe_window, text="Quantity: ")   ## Making quantity label ## 
     quantity_label.grid(row=3, column=0) 
     quantity_box = Entry(new_recipe_window)         ## Making quantity entry ## 
     quantity_box.grid(row=3, column=1) 

     unit_label = Label(new_recipe_window, text="Unit: ")     ## Making unit label ## 
     unit_label.grid(row=4, column=0) 
     unit_box = Entry(new_recipe_window)          ## Making unit entry ## 
     unit_box.grid(row=4, column=1) 

     def write(): 
      a = recipe_name_box.get() 
      b = num_people_box.get() 
      c = item_box.get() 
      d = quantity_box.get() 
      e = unit_box.get() 

      line = (a, b, c, d, e) 
      datafile.write(str(line) + "\n") 
      datafile.close() 

      saved_recipes.config(a) 

      close(new_recipe_window) 

      script() 



     finish_button = Button(new_recipe_window, text="Save and Finish", command=write)  ## Making finish button ## 
     finish_button.grid(row=5, column=0, sticky=S) 




    # Dropdown Box # 

    default = StringVar(start_window, 'Recipe 1') 
    default.set("Select Your Recipe") 

    saved_recipes = OptionMenu(start_window, default, "Hi") 
    saved_recipes.grid(row=0, column=1) 

    # Dropdown Box # 



    # New Recipe Button # 

    new_recipe = Button(start_window, text="New Recipe", command=new_recipe) 
    new_recipe.grid(row=0, column=0) 

    # New Recipe Button # 

script() 

(Извините за блок, я думаю, что все полезно ответить на возможно?)

+0

Вы ищете способ мониторинга файла для внесения изменений или заполнения «OptionMenu»? – Jasper

+0

@ Jasper Sort - Я хочу обновить параметры в виджете OptionMenu, чтобы отобразить первый индекс в списках в файле данных, который я сделал. – 18166

ответ

1

Я считаю, что у вас есть два различных варианта.

Один из вариантов, который вы могли бы сделать, - установить таймер, чтобы проверять текстовый файл каждые пару секунд, посмотреть, полностью ли он изменен, и соответственно обновить OptionMenu. Вы можете найти более подробную информацию о том, как это сделать here, но в двух словах, вы хотите, чтобы ваш код, чтобы выглядеть примерно так:

def recheck(root, option_menu, file_name): 
    with open(file_name) as my_file: 
     lines = my_file.readlines(): 
     # `lines` is a list where each item is a single line 
     # do any checks and updates you need here. 

    root.after(1000, recheck, root, option_menu, file_name) 
    # schedule the function to run again after 1000 milliseconds. 

def script(): 
    # set up your gui 

    start_window.after(1000, recheck, start_window, option_menu, "StoredRecipies.txt") 

Примечание: Вы можете найти более подробную информацию о with заявлении здесь: http://effbot.org/zone/python-with-statement.htm

Недостатком этого является то, что обновление будет немного отсталым - вы в конечном итоге перепроверяете файл только один раз в секунду, поэтому обновление не будет мгновенным.

В качестве альтернативы вы можете использовать что-то вроде Watchdog. Это сторонняя библиотека, которую вы можете настроить для «просмотра» определенного файла и запуска функции при каждом изменении файла. Это гораздо более отзывчиво в том, что вы вызовете функцию только в том случае, если файл действительно изменится, но может оказаться сложнее, поскольку вам нужно выяснить, как заставить его работать с Tkinter. Я собираюсь предположить, что ваш код будет выглядеть примерно так:

import os.path 
from watchdog.events import FileSystemEventHandler 
from watchdog.observers import Observer 

def setup_observer(option_menu, filename): 
    normalized_filename = os.path.normpath(input_filename) 

    class MyEvent(FileSystemEventHandler): 
     def on_modified(self, event): 
      if os.path.normpath(event.src_path) == normalized_filename: 
       # update your option menu 

    observer = Observer() 
    observer.schedule(MyEvent(), '.', recursive=False) 
    return observer 

def script(): 
    # setup gui 

    observer = setup_observer(option_menu, "myfile.txt") 

    start_window.mainloop() 
+0

Я думаю, что предпочел бы использовать первый - только потому, что я его понимаю. Несколько вопросов: вы замечаете, что проверяете свой файл, я не уверен, как это сделать, мог бы я сделать datafile.readline() или что? – 18166

+0

@ 18166 - более или менее да. Я бы на самом деле повторно открыть файл и прочитать его снова, а не повторно использовать файл данных.В конце концов вы должны закрыть каждый файл, который вы открываете, и лучше сделать это раньше, а не позже, чтобы вы не забыли об этом. Я редактировал свой вопрос, чтобы добавить более подробную информацию. – Michael0x2a

+0

Что нужно добавить в параметры OptionMenu (OptionMenu (root и т. Д.))? Я не могу найти, что добавить туда, чтобы использовать это. – 18166

0

Чтобы добавить элементы в OptionList, вы можете использовать следующий метод (от http://www.prasannatech.net/2009/06/tkinter-optionmenu-changing-choices.html)

datafile = open("StoredRecipes.txt", "r") 
    for line in datafile.readlines(): 
    saved_recipes['menu'].add_command(label=line, 
     command=lambda temp = line: saved_recipes.setvar(saved_recipes.cget("textvariable"), value = temp)) 

который использует (имеет использовать) закрытие и анонимную функцию - определенно ничего не нужно иметь на вашем уровне опыта (угадывание из структуры вашего кода).

Этот фрагмент добавляет команду для каждой строки в вашем файле. Поскольку OptionMenu - это то, что выполняет элементы при выборе элементов, вам необходимо предоставить команду для каждой строки. Прямо сейчас это просто указывает отображаемый текст на выбранную строку.

Для этого используется анонимная функция (lambda), которая устанавливает textvariable из OptionMenu в текущую строку.

 Смежные вопросы

  • Нет связанных вопросов^_^