【问题标题】:How do I delete a Tkinter label using a button command?如何使用按钮命令删除 Tkinter 标签?
【发布时间】:2020-10-22 08:55:36
【问题描述】:

我希望我的程序以这样一种方式运行,一旦用户按下 Info 按钮,由于来自 Info 的命令,会显示一个名为 GameInfoLabel 的标签按钮。在相同的条件下(如果按下 Info 按钮),我想添加一个 Back 按钮来删除/销毁GameInfoLabel

我试图在下面的代码中实现这一点,但我收到了消息

NameError:名称“GameInfoLabel”未定义。

from tkinter import * 

root = Tk() 
root.title("Game Menu") 
root.geometry("1920x1080")  
root.resizable(True, True) 

def QuitGameInfo():
    GameInfoLabel.destroy()
    BackInfoButton['state'] = NORMAL


def GameInfo(): 
    RulesNotepad = open("GameInfo.txt",'r')
    Rules = RulesNotepad.read()
    GameInfoLabel = Label(root, text = Rules, fg = "blue", bg = "red", height = "14", width = "140").pack()
    BackInfoButton = Button(root, text = "Back", command = QuitGameInfo).pack() 
    RulesNotepad.close()

button3 = Button(root, text = "Info", command = GameInfo, width = "20", height = "3").pack()

root.mainloop()

【问题讨论】:

  • 您的代码中存在一些问题:1) GameInfoLabelGameInfo() 内部的局部变量,因此无法在 QuitGameInfo() 内部访问。这会导致错误; 2)GameInfoLabelNone,因为它是Label(...).pack() 的结果; 3)GameInfoButton里面QuitGameInfo()没有定义。
  • 为什么将BackInfoButton['state'] 更改为NORMAL,因为它已经处于NORMAL 状态?
  • 我不知道为什么我现在回过头来看这行。

标签: python python-3.x user-interface tkinter python-3.7


【解决方案1】:

错误是由于GameInfoLabelGameInfo() 内部的局部变量,在QuitGameInfo() 内部不可访问。

您可以通过将GameInfoLabel 声明为全局或通过参数将其传递给QuitGameInfo() 来修复此错误。同样适用于BackInfoButton

但是您需要解决另一个问题:GameInfoLabelBackInfoButton 都是 None,因为它们是 pack() 的结果。

以下是使用全局解决方案修改后的代码:

from tkinter import * 

root = Tk() 
root.title("Game Menu") 
root.geometry("1920x1080")  
root.resizable(True, True) 

def QuitGameInfo():
    GameInfoLabel.destroy()
    #BackInfoButton['state'] = NORMAL   # why ??? Should it be destroyed as well?
    BackInfoButton.destroy()


def GameInfo():
    global GameInfoLabel, BackInfoButton 
    with open("GameInfo.txt",'r') as RulesNotepad:
        Rules = RulesNotepad.read()
    GameInfoLabel = Label(root, text = Rules, fg = "blue", bg = "red", height = "14", width = "140")
    GameInfoLabel.pack()
    BackInfoButton = Button(root, text = "Back", command = QuitGameInfo)
    BackInfoButton.pack() 

Button(root, text = "Info", command = GameInfo, width = "20", height = "3").pack()

root.mainloop()

但是我建议使用框架来容纳GameInfoLabelBackInfoButton,并且框架最初是隐藏的。当 Info 按钮被点击时,显示框架。当 Back 按钮被点击时,隐藏框架。

from tkinter import * 

root = Tk() 
root.title("Game Menu") 
root.geometry("1920x1080")  
root.resizable(True, True) 

def GameInfo():
    with open("GameInfo.txt",'r') as RulesNotepad:
        Rules = RulesNotepad.read()
    GameInfoLabel.config(text=Rules)
    info_frame.pack()  # show the game info frame

Button(root, text="Info", command=GameInfo, width="20", height="3").pack()

# create the game info frame but don't show it initially
info_frame = Frame(root)
GameInfoLabel = Label(info_frame, fg="blue", bg="red", height="14", width="140")
GameInfoLabel.pack()
Button(info_frame, text="Back", command=info_frame.pack_forget).pack()

root.mainloop()

【讨论】:

    【解决方案2】:

    正如 acw1668 的评论中提到的,GameInfoLabelGameInfo() 方法的本地化。这意味着一旦此方法完成运行,其中声明的任何内容都将不复存在。

    通常的解决方案是将变量传递/返回给函数以获取结果,例如您的游戏信息可以返回标签,但是因为您希望在事件发生时自动调用这些函数,例如你的按钮被按下了,这并不容易。

    我相信解决您的问题的最简单方法是全局声明 GameInfoLabel 变量(在全局范围内),这并不总是最佳编码实践,但我不确定 tkinter 是否能够将变量参数传递给一个事件处理程序,这可能很复杂。

    同样如 acw1668 所述,您可以立即在从初始化 Label(...) 返回的新标签上调用 .pack()。然后 Pack 不会返回标签,因此我们单独执行此操作。

    这应该可行,请仔细阅读。

    from tkinter import * 
    
    root = Tk() 
    root.title("Game Menu") 
    root.geometry("1920x1080")  
    root.resizable(True, True) 
    
    # Declare any global UI Components
    GameInfoLabel = None # Dont set a Label yet
    
    def QuitGameInfo():
        GameInfoLabel.destroy()
        BackInfoButton['state'] = NORMAL
    
    def GameInfo(): 
        RulesNotepad = open("GameInfo.txt",'r')
        Rules = RulesNotepad.read()
        GameInfoLabel = Label(root, text = Rules, fg = "blue", bg = "red", height = "14", width = "140")
        GameInfoLabel.pack()
    
        BackInfoButton = Button(root, text = "Back", command = QuitGameInfo).pack() 
        RulesNotepad.close()
    
    button3 = Button(root, text = "Info", command = GameInfo, width = "20", height = "3")
    button3.pack()
    
    root.mainloop()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-06
      • 2021-11-18
      • 1970-01-01
      • 2013-10-28
      • 2019-11-29
      • 2021-04-14
      • 2023-02-24
      相关资源
      最近更新 更多