2016-01-27 1 views
2

У меня есть приложение gui, которое имеет несколько окон и кнопок для продвижения вперед и назад. Для этого я использую контроллер и поднимаю рамки вверху при каждом изменении окна. Вот мой код для контроллера и типичный фрейм.Как сделать метод, который запускается каждый раз, когда кадр отображается в tkinter

import Tkinter as tk # python 
from tkFileDialog import askopenfilename, asksaveasfilename 
from analyzer import Options 

TITLE_FONT = ("Helvetica", 18, "bold") 

class TennisProgram(tk.Tk): 

    def __init__(self, *args, **kwargs): 
     tk.Tk.__init__(self, *args, **kwargs) 

     # the container is where we'll stack a bunch of frames 
     # on top of each other, then the one we want visible 
     # will be raised above the others 
     container = tk.Frame(self) 
     #Allow the window to be resized 
     # container.resizable(width=True, height=True) 
     container.pack(side="top", fill="both", expand=True) 
     container.grid_rowconfigure(0, weight=1) 
     container.grid_columnconfigure(0, weight=1) 
     #List of options bundles. One bundle for each video 
     self.options_bundle_list = {} 
     self.frames = {} 
     #Init empty array to hold the list of files 
     #Placed in the container so that all views can access it 
     self.files = [] 

     for F in (UploadPage, AnalysisOptionsPage, FormAnalysisOptions, MatchAnalysisOptions, MatchAnalysisOptionsPage2, OutputPage, ProcessingPage): 
      page_name = F.__name__ 
      frame = F(container, self) 
      self.frames[page_name] = frame 

      # put all of the pages in the same location; 
      # the one on the top of the stacking order 
      # will be the one that is visible. 
      frame.grid(row=0, column=0, sticky="nsew") 
     # Name the window 
     self.title("Tennis Analyzer") 
     self.show_frame("UploadPage") 

    def show_frame(self, page_name): 
     '''Show a frame for the given page name''' 
     frame = self.frames[page_name] 
     frame.tkraise() 


class UploadPage(tk.Frame): 
#TODO Add logic to remove a file path from the list 
    def __init__(self, parent, controller): 
     tk.Frame.__init__(self, parent) 
     self.controller = controller 
     self.createView() 


    def createView(self): 
     label = tk.Label(self, text="Upload Videos for Analysis", font=TITLE_FONT) 
     label.pack(side="top", fill="x", pady=10) 

     #Listbox to display the list of files to be processed 
     self.path_list = tk.Listbox(self) 
     #Additional options allow listbox to expand as the window is resized 
     self.path_list.pack(fill=tk.BOTH ,expand=True) 

     for path in self.controller.files: 
      self.path_list.insert(tk.END, path) 

     add_vidoes_button = tk.Button(self, text="Add Videos", 
          command=self.choose_files) 
     continue_button = tk.Button(self, text="Continue", 
          command=lambda: self.controller.show_frame("AnalysisOptionsPage")) 
     add_vidoes_button.pack(side=tk.TOP) 
     continue_button.pack(side=tk.BOTTOM) 

    def choose_files_paths(self): 
     #don't want a full GUI, so keep the root window from appearing 
     #self.controller.withdraw() 
     #Get a file name from the user 
     filename = askopenfilename() 
     #Add it to the list of files to be processed 
     self.controller.files.append(filename) 
     self.path_list.insert(tk.END, filename) 

код, который я пишу в инициализации получает выполняется один раз и создает представление, но мне было интересно, если это было возможно иметь функцию, которая запускается каждый раз, когда кадр был поднят, похожий на onResume функцию в Android. Я хотел бы сделать это, если некоторые базовые данные изменились, как на этой странице загрузки. Например, что, если элемент удаляется из массива, который заполняет список, я бы хотел его обновить.

+1

вы можете добавить код в 'show_frame' – furas

+0

@furas Очевидно, я мог бы добавить какой-то способ и взломать что-то, что работает, я просил выяснить, существует ли какое-то соглашение, которое существовало или документация, которую я упускал из виду. – user3282276

ответ

5

Tkinter имеет события низкого уровня, такие как <Visibility> и <Map>, которые должны срабатывать при смене страниц. К сожалению, они не работают надежно на всех платформах.

Простейшим и наиболее надежным решением является создание собственного события. Во-первых, изменить show_frame послать событие в окно, когда оно показано:

def show_frame(self, page_name): 
    ... 
    frame.event_generate("<<ShowFrame>>") 

Далее, каждая страница может связываться с этим событием, если это необходимо, чтобы получить уведомление, когда оно становится видимым:

class UploadPage(tk.Frame): 
    def __init__(self, parent, controller): 
     ... 
     self.bind("<<ShowFrame>>", self.on_show_frame) 

    def on_show_frame(self, event): 
     print("I am being shown...") 
+0

Спасибо, это именно то, что Я искал – user3282276

+0

Это выглядит великолепно. Что делать, если on_show_frame возвратил переменные, которые мне нужно было назначить? –

+0

@ Luke.py: функции, вызываемые из привязок, не могут возвращать данные, потому что вызывающий объект не является вашим кодом. Вызывающий - mainloop, который игнорирует (почти) все данные, которые возвращаются (с «почти» частью, которая относится к возврату строки '' break "' специально) –

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