Python 3:Tkinter帧和意外行为

时间:2017-01-20 15:17:39

标签: python python-3.x tkinter

我正在尝试在tkinter中创建一个具有多个屏幕的程序,但是我遇到了一个奇怪的问题:当我尝试将特定屏幕提升到前面时,它不会出现。我用来创建不同屏幕的代码是:

class PokemonDecklistCreatorApp(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)
        container.pack(side='top', fill='both', expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for F in (MainMenu, DecksMenu, DeckEditor, CardViewerDeckEditor,DeckNotes,SearchMenu, StandardSearch, AdvancedSearch, RandomSearch, SearchResults,CardViewerSearchResults, ExtrasMenu, CardExplanationGuide, AboutProgram):
            try:
                frame = F(parent=container, controller=self)
                pageName = F.__name__
                self.frames[pageName] = frame
                frame.grid(row=0, column=0, sticky='nsew')
            except Exception as e:
                print(e)
        self.show_frame('MainMenu')

    def show_frame(self, page):
        frame = self.frames[page]
        frame.tkraise()

然后用户可以使用搜索屏幕指定要搜索的条件,然后调用doSearch函数,该函数应该销毁旧的SearchResults屏幕(通过从self.frames dict和垃圾收集中弹出)。

class RandomSearch(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        self.parent = parent
        [some widgety code here]
        self.btnSearch = tk.Button(self, text='Gotta Search \'em All!', command=self.doSearch, font=('Lucida Grande',24))
        self.btnSearch.place(x=450, y=670, width=500, height=40)

    def doSearch(self,* args,** kwargs):
        self.controller.frames.pop('SearchResults')
        frame=SearchResults(parent=self.parent,controller=self.controller,searchTerms=[])
        pageName = SearchResults.__name__
        self.controller.frames[pageName]=frame
        self.controller.show_frame('SearchResults')


class SearchResults(tk.Frame):

    def __init__(self, parent, controller,searchTerms=None):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        [more widgety stuff]

然而,问题是当我尝试运行doSearch函数时,它会创建新对象但不显示它。它保持在同一个屏幕上,我仍然可以像往常一样与它进行交互,就好像它根本没有改变scrreens!

我已经通过将print(id(self.frames['SearchResults']))放入show_frame函数来检查新对象的创建,并且每次按下按钮时都会显示不同的ID。

我也知道问题不在self.controller.show_frame('SearchResults')行,因为我已经尝试了self.controller.show_frame('MainMenu'),这样可以正常工作。

我做错了什么?

1 个答案:

答案 0 :(得分:3)

考虑以下代码:

def doSearch(self,* args,** kwargs):
    ...
    frame=SearchResults...)
    pageName = SearchResults.__name__
    self.controller.frames[pageName]=frame
    self.controller.show_frame('SearchResults')

您永远不会通过调用grid来添加控制器的帧。您可能需要添加此声明:

    frame.grid(row=0, column=0, sticky='nsew')

我无法看到任何理由需要从列表中删除一个帧(不破坏它!)并在其位置放置一个新帧。您已经创建了内存泄漏。 Intead,您应该在SearchResults中添加一个方法,重新创建或重置现有SearchResults页面内的小部件。