简体   繁体   English

Python 3:Tkinter框架和意外行为

[英]Python 3: Tkinter frames and unexpected behaviour

I'm currently trying to create a program in tkinter that has multiple screens, however I am running into a strange problem:when I try to raise a particular screen to the front, it doesnt appear. 我目前正在尝试在tkinter中创建一个具有多个屏幕的程序,但是我遇到了一个奇怪的问题:当我尝试将特定屏幕提升到前面时,它没有出现。 The code I use to create the differnt screens is this: 我用来创建不同屏幕的代码是这样的:

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

Then the user can use the Search Screens to specify the criteria to search for, then the doSearch function is called which should destroy the old SearchResults screen (by popping from the self.frames dict and garbage collecting). 然后,用户可以使用“搜索屏幕”指定要搜索的条件,然后调用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]

However, the problem is that when I try running the doSearch function it creates the new object but doesn't display it. 但是,问题在于,当我尝试运行doSearch函数时,它将创建新对象,但不显示它。 It remains on the same screen and I can still interact with it as usual, as if it didnt change scrreens at all! 它保留在同一屏幕上,我仍然可以像往常一样与它进行交互,就好像它根本没有改变屏幕一样!

I have checked the creation of new objects by putting print(id(self.frames['SearchResults'])) in the show_frame function and it shows a different ID each time I press the button). 我已经通过将print(id(self.frames['SearchResults']))放在show_frame函数中来检查是否创建了新对象,每次按下按钮时,它都会显示一个不同的ID。

I also know that the problem is not with the self.controller.show_frame('SearchResults') line as I have tried self.controller.show_frame('MainMenu') and this worked as expected. 我也知道问题不在于self.controller.show_frame('SearchResults')行,因为我尝试了self.controller.show_frame('MainMenu')并且按预期工作。

What have I done wrong? 我做错了什么?

Consider this code: 考虑以下代码:

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

You never add the frame the the controller by calling grid . 永远不要通过调用grid将框架添加到控制器中。 You likely need to add this statement: 您可能需要添加以下语句:

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

I can't see any reason for needing to take a frame off of the list (without destroying it!) and putting a new one in its place. 我看不出有任何理由需要从列表中删除一个框架(而不破坏它!)并放置一个新的框架。 You've created a memory leak. 您创建了内存泄漏。 Intead, you should just add a method in SearchResults that recreates or resets the widgets inside the existing SearchResults page. Intead,您只需在SearchResults中添加一个方法即可在现有SearchResults页面内重新创建或重置小部件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM