【问题标题】:Python: calling a parent class method to deconfiey a windows (Tkinter) causes two sets of the widgets in the windowPython:调用父类方法来解除窗口(Tkinter)会导致窗口中的两组小部件
【发布时间】:2017-04-15 12:42:03
【问题描述】:

对于我的任何愚蠢或无知,我深表歉意,但我是 Python 的新手,一般来说都是编码的新手。我一直在尝试为我将要制作的游戏制作 UI,作为自学 python 的一种方式,我有一个主窗口和一些按钮小部件。 Play game 按钮打开第二个窗口(用于游戏本身)并使用 .withdraw 方法隐藏根窗口。这完美地工作。在游戏窗口内我有另一个按钮,我想销毁游戏窗口并将用户带回我已撤回的根菜单窗口。这似乎有效,除了每次我调用它时,它都会在窗口中创建一组新的、重复的小部件,所以我最终得到了多组。

我将在底部发布我的完整代码,但这里是我认为相关的部分。

一个 tkinter 按钮在父类(主窗口)中调用它。这很好用。

def playGame(self):     #Start the main game window
    self.master.withdraw()
    gameWindow()

我在子类中使用下面的方法来销毁游戏窗口,然后调用父类中的方法来恢复之前撤回的窗口

def exitMenu(self):
    self.g.destroy()
    UI(root).showMenu()

这有效,只是它每次都复制小部件导致显示:

screen capture of result

下面是我的全部代码,非常感谢您的帮助。

import tkinter as tk
import PIL
from Config import *

root = tk.Tk()

class UI(): #Main Menu

    def __init__(self, master):

        #Create Main Menu Window

        self.master = master
        self.master.title("Monopoly")
        self.master.wm_iconbitmap('icons\Monopoly-Icon.ico')
        self.master.geometry((resolution))

        #Menu Buttons

        self.label = tk.Label(master, text= 'Welcome to Monopoly! PLACEHOLDER')
        self.playButton = tk.Button(master, text= 'Play Game', command= self.playGame)
        self.settingsButton = tk.Button(master, text= 'settings', command= self.settings)
        self.exitButton = tk.Button(master, text= 'Exit', command= self.exitGame)

        self.label.grid(columnspan=2)
        self.playButton.grid(column=0)
        self.settingsButton.grid(column=0)
        self.exitButton.grid(column=0)

    def settings(self):       #Opens Settings Window
        s = tk.Toplevel()
        s.title('Settings')
        s.wm_iconbitmap('icons\Monopoly-Icon.ico')
        s.geometry((resolution))
        self.master.withdraw()
        resLabel = tk.Label(s, text= 'Resolution')
        resOption = tk.OptionMenu(s, resolution, *resList)

        resLabel.grid(column=0,row=0)
        resOption.grid(column=0, row=4)

    def showMenu(self):     #Bring back menu windwow
        self.master.deiconify()

    def exitGame(self):    #Exit Game Method
        root.destroy()

    def playGame(self):     #Start the main game window
        self.master.withdraw()
        gameWindow()

class gameWindow(UI):

    def __init__(self):

        self.g = tk.Toplevel()
        self.g.title('Monopoly')
        self.g.wm_iconbitmap('icons\Monopoly-Icon.ico')
        self.g.geometry((resolution))

        self.menuButton = tk.Button(self.g, text= 'Main Menu', command= self.exitMenu)

        self.menuButton.grid(column=0,row=0)

    def exitMenu(self):
        self.g.destroy()
        UI(root).showMenu()

mainMenu = UI(root)

root.mainloop()

【问题讨论】:

    标签: python tkinter


    【解决方案1】:

    你应该将父类UI传递给子类gameWindow,然后你可以在子类中使用父类的showMenu()方法。

    从子窗口显示主窗口的代码将是: self.mainUI.showMenu() 而不是 UI(root).showMenu()

    子类变成:

    class gameWindow(UI):
    
        def __init__(self, mainUI): # Make the main window a parameter/attribute
    
            self.mainUI = mainUI # Make the main window a parameter/attribute
            self.g = tk.Toplevel()
            self.g.title('Monopoly')
            self.g.wm_iconbitmap('icons\Monopoly-Icon.ico')
            self.g.geometry((resolution))
    
            self.menuButton = tk.Button(self.g, text= 'Main Menu', command= self.exitMenu)
    
            self.menuButton.grid(column=0,row=0)
    
        def exitMenu(self):
            self.g.destroy()
            self.mainUI.showMenu()
    

    gameWindow 现在需要一个参数,因此您将其作为self 传递给主用户界面

    def playGame(self):     #Start the main game window
            self.master.withdraw()
            gameWindow(self)
    

    你可以阅读更多关于隐藏/显示窗口here

    这里是完整的代码:

    import tkinter as tk
    import PIL
    from Config import *
    
    root = tk.Tk()
    
    class UI(): #Main Menu
    
        def __init__(self, master):
    
            #Create Main Menu Window
    
            self.master = master
            self.master.title("Monopoly")
            self.master.wm_iconbitmap('icons\Monopoly-Icon.ico')
            self.master.geometry((resolution))
    
            #Menu Buttons
    
            self.label = tk.Label(master, text= 'Welcome to Monopoly! PLACEHOLDER')
            self.playButton = tk.Button(master, text= 'Play Game', command= self.playGame)
            self.settingsButton = tk.Button(master, text= 'settings', command= self.settings)
            self.exitButton = tk.Button(master, text= 'Exit', command= self.exitGame)
    
            self.label.grid(columnspan=2)
            self.playButton.grid(column=0)
            self.settingsButton.grid(column=0)
            self.exitButton.grid(column=0)
    
        def settings(self):       #Opens Settings Window
            s = tk.Toplevel()
            s.title('Settings')
            s.wm_iconbitmap('icons\Monopoly-Icon.ico')
            s.geometry((resolution))
            self.master.withdraw()
            resLabel = tk.Label(s, text= 'Resolution')
            resOption = tk.OptionMenu(s, resolution, *resList)
    
            resLabel.grid(column=0,row=0)
            resOption.grid(column=0, row=4)
    
        def showMenu(self):     #Bring back menu windwow
            self.master.deiconify()
    
        def exitGame(self):    #Exit Game Method
            root.destroy()
    
        def playGame(self):     #Start the main game window
            self.master.withdraw()
            gameWindow(self)
    
    class gameWindow(UI):
    
        def __init__(self, mainUI): # Make the main window a parameter/attribute
    
            self.mainUI = mainUI # Make the main window a parameter/attribute
            self.g = tk.Toplevel()
            self.g.title('Monopoly')
            self.g.wm_iconbitmap('icons\Monopoly-Icon.ico')
            self.g.geometry((resolution))
    
            self.menuButton = tk.Button(self.g, text= 'Main Menu', command= self.exitMenu)
    
            self.menuButton.grid(column=0,row=0)
    
        def exitMenu(self):
            self.g.destroy()
            self.mainUI.showMenu()
    
    mainMenu = UI(root)
    
    root.mainloop()
    

    【讨论】:

    • 非常感谢您抽出宝贵时间提供帮助。这阻止了我将笔记本电脑扔出窗外! =) 在我的原始代码中,我假设我调用了 UI 类本身,然后调用了 showMenu 方法?这是否意味着从另一个类调用一个类方法,它必须始终是我要调用的类的子类?
    • 我很高兴它有帮助:)。
    • 不,您并不总是需要将一个类传递给另一个类才能在第二个类中使用第一个类的方法。这完全取决于两个类之间的交互以及它们的作用。在您的情况下,您在 gameWindow 之外创建了 UI 的实例;因此gameWindow 无法访问UI 的方法。
    • 如果UI 的实例是在gameWindow 中创建的,您可以使用它的方法而不将其设为“子”。这与调用UI 类后跟showMenue 方法(UI(root).showMenu()) 时所做的类似。但是,这创建了另一个 UI 实例。但是因为UI 的第一个和第二个实例都具有相同的root -全局变量- 作为父级,所以它没有创建两个窗口,而是创建了两组小部件,因此重复了按钮.
    猜你喜欢
    • 2019-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-14
    • 2014-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多