0

I am making a story-based game on Tkinter and I what I want is that once the play clicks the next button, or makes a decision I want that block of text to disappear so the player can focus on the next set of text and decisions.

I tried to make a labelname.destroy and a labelname.pack_forget in the functions that the user chooses for example, the user chooses the button 'join' then the program would go into def join():, and inside that function would be labelname.destroy, so that block of text would delete, but it's not working for some reason. So now I've attempted to create a clear_label function that I can call instead, but that,s not working either. Please help!

code:
from tkinter import *
from tkinter import ttk
from tkinter.simpledialog import askstring
from tkinter.messagebox import showinfo
from PIL import Image, ImageTk

#Tkinter window
window= Tk()
window.geometry("600x400") #size of window
window.title("Escape the Addiction: A Quest for Balance")

#defining the score value inorder to give different outputs when the next button is clicked
score = 1

def ask_name():
  global name
  window.iconify() #minimize main window
  #asks user for name input 
  name = askstring('Name', 'What is your name?')
  showinfo('Hello!', 'Hi, {}'.format(name))
  game()

#when the start button is clicked a new screen window is opened which is the actual game
def game():
  global dialogue_1, dialogue_2, Leave, Join, dialogue_3, dialogue_4, game_Screen, next_button, next_button1
  
  #window theme
  style = ttk.Style()
  game_screen = Toplevel(window)
  game_screen.geometry("600x400")
  game_screen.title("The Quest")
  print("You are now in the new window!")


  #when the next button gets clicked
  def next():  
    global score
    
    if score == 0:
      story_line.config(text='Welcome to Escape the Addiction: A Quest for Balance, {}'.format(name))
      print('The text is changing')
      score +=1

    elif score == 1:
      story_line.config(text='This is an interactive story game!')
      print('The text is changing again')
      score +=1

    elif score == 2:
      story_line.config(text='where you will be given a scenario and will have the power to drive the story.')
      print('The text is changing again')
      score +=1
    
    elif score == 3:
      story_line.config(text='But be careful, your decisions will result in your ending.')
      print('The text is changing again')
      score +=1
  
    elif score == 4:
      story_line.config(text='Will you escape the addiction?')
      print('The text is changing again')
      score +=1
  
    else:
      storyline1()
      story_line.config(text='')

  #function to clear the first 2 labels once the next button is clicked
  def clear_label():
    dialogue_1.destroy()
    dialogue_2.destroy()
    Leave.destroy()
    Join.destroy()

  def clear_label2():
    global dialogue_3
    dialogue_3.destroy()

  def clear_label3():
    dialogue_4.destroy()

  def clear_label4():
    dialogue_5.pack_forget()
    Ignore.pack_forget()
    Listen.pack_forget()

    
  def storyline1():
    global dialogue_1, dialogue_2, Leave, Join, dialogue_3, dialogue_4, game_Screen, next_button, next_button1
    print("We made it")
    dialogue_1 = Label(game_screen, text='A thrilling gaming tournament awaits you as you enter a big gaming stadium. The atmosphere is electric, and players from all walks of life are competing fiercely.', wraplength=300)
    dialogue_1.pack()
    
    dialogue_2 = Label(game_screen, text='Do you join the tournament?')
    dialogue_2.pack()
    
    #join button
    Join = Button(game_screen,text="Join", width= 5, height= 2, command=decision_1, font=("Helvetica", 12), anchor=S)
    Join.pack()
    #Leave button
    Leave = Button(game_screen, text="LEAVE", width= 5, height= 2, command=decision_2, font=("Helvetica", 12), anchor=S)
    Leave.pack()

  #2 different functions to branch the stories
  #you join the tournament
  def decision_1():
    print("You made it to decision 1")
    dialogue_3 = Label(game_screen,text="You decide to join the tournament, hooked to the excitement. However, you lose track of time and become deeply engrossed with the games", wraplength=300)
    dialogue_3.pack()

    #displaying next button
    next_button1 = Button(game_screen, text='NEXT', width= 5, height= 2, command=wizard, font=("Helvetica", 12), anchor=S)
    next_button1.pack(pady=5)

  #removing previous buttons
    clear_label()
    
  #you leave the tournament area
  def decision_2():
    print("You made it to decision 2")
    dialogue_4 = Label(game_screen,text="You choose to explore the arena in search of an exit, despite the allure of the competition. After a while of searching, you discover a hidden shortcut that allows you to get around the tournament and continue your adventure.", wraplength=300)
    dialogue_4.pack()

    #displaying next button
    next_button1 = Button(game_screen, text='NEXT', width= 5, height= 2, command=wizard, font=("Helvetica", 12), anchor=S)
    next_button1.pack(pady=5)

    #removing previous buttons
    clear_label()
    
  #both decisions go back to the wizard
  def wizard():
    dialogue_5 = Label(game_screen, text='As you go about on your adventure you encounter a wise wizard in the gaming arena. He seems eager to share his knowledge about gaming addiction and the importance of balance. Do you...', wraplength=300)
    dialogue_5.pack()
    Listen = Button(game_screen, text="LISTEN TO THE WISE WIZARD", width= 25, height= 2, command=listen, font=("Helvetica", 12), anchor=S)
    Listen.pack()
    Ignore = Button(game_screen, text="IGNORE THE WIZARD", width= 18, height= 2, command=ignore, font=("Helvetica", 12), anchor=S)
    Ignore.pack()

  #clearing previous options
  clear_label2()
  clear_label3()
  
  def listen():
    print("You made it to listening")
    dialogue_6 = Label(game_screen, text='You decide to give the Wise Wizard a moment of your time. He teaches you valuable lessons about setting boundaries with tech, managing screen time, and doing other activites.', wraplength=250)
    dialogue_6.pack()
    showinfo("Ending 1/2 (Good ending)", "You made the right choice listening to the wizard! After your conversation you learn how to maintain a balance between gaming and real-life responsibilites. The door to the exit is shining brightly waiting for your leave.")


    #erasing previous Text
    clear_label4()
    
  def ignore():
    print("Why did u ignore him ;d")
    dialogue_7 = Label(game_screen, text='You decide to ignore the Wise Wizard.')
    dialogue_7.pack()
    showinfo("Ending 2/2 (Bad ending)", "Despite ignoring the wizard's warnings, you become entangled in the gaming tournament, losing track of time and neglecting balance. As a result, the exit is blocked by a chaotic and unsettling environment and crowd as a result you are stuck there forever.")


    clear_label4()

  #text for story
  story_text = [
    "Welcome to Escape the Addiction: A Quest for Balance, {}".format(name),
    'This is an interactive story game where you will be given',
    'a scenario and will have the power to drive the story',
    'But be careful, your decisions will result in your ending.',
    'Will you escape the addiction?'
  ]

  #next button
  next_button = Button(game_screen, text='NEXT', width= 5, height= 2, command=next, font=("Helvetica", 12), anchor=S)
  next_button.pack(pady=5)

  #actually starting to create the popup text that tells the story
  story_line = Label(game_screen, text=story_text[0], font=("Helvetica", 12))
  story_line.pack(pady= 5)

  game_screen.mainloop()
  

#creating windows
menu = Canvas(window, width=600, height=400, bg="black")
menu.pack()


#creating background image for intro screen
IntroImg = PhotoImage(file="Intro.png")
Introbg = menu.create_image(0, 0, anchor=NW, image=IntroImg)

#inputting button
start_button = Button(menu, text="START", width= 10, height= 2, command=ask_name, font=("Helvetica", 12), anchor=S)
start_button.place(x=230, y=300)

1 Answer 1

0

Your approach to using global variables makes sense in general, but there would be too many variables in this case. Instead of global variables, you can give your widgets unique names and then destroy them using the nametowidget method. Alternatively, you can wrap your widgets in a separate frame and then destroy them using the winfo_children method.

Here is a demonstration of both methods:

import tkinter as tk

    
def clear1(parent=None):
    parent = parent if parent else root
    for i in parent.winfo_children():
        i.destroy()

def clear2(widgets):
    for i in widgets:
        try:
            root.nametowidget(i).destroy()
        except KeyError as e:
            print(e)
            pass
    
def create_widgets(parent):
    del_all_button = tk.Button(parent, text="Delete All", command=clear1)
    del_all_button.pack()
    
    frame = tk.Frame(parent)
    frame.pack()
    frame_label = tk.Label(frame, text="Label in Frame")
    frame_label.pack()
    # passing the parent object (widget) to the clear1 function
    button = tk.Button(parent, text="Delete Label in Frame",
                       command=lambda: clear1(frame))
    button.pack()

    # unique names
    first_label = tk.Label(parent, text="Label 1", name="first_label")
    first_label.pack()
    second_label = tk.Label(parent, text="Label 2", name="second_label")
    second_label.pack()
    # passing a list of unique widget names to the clear2 function
    del_button = tk.Button(parent, text="Delete Label 1, Label 2, and Button",
                        command=lambda: clear2(["first_label", "second_label", "delete_button"]),
                        name="delete_button")
    del_button.pack()

    
root = tk.Tk()
root.geometry("600x400")
root.title("Window")

create_widgets(root)

root.mainloop()

Universal widget methods


Since your application will create many widgets, it may be more convenient to use a separate frame for items that are constantly being removed.

The following example shows one way to create and delete elements in a frame. This is pretty close to your current quest flow, but you may need to adjust it for future changes.

import tkinter as tk
from tkinter.simpledialog import askstring
from tkinter.messagebox import showinfo

        
root = tk.Tk()
root.geometry("600x400")
root.title("Window")


def ask_name():
    global name
    root.iconify()
    name = askstring('Name', 'What is your name?')
    showinfo('Hello!', 'Hi, {}'.format(name))
    create_toplevel()
  
def create_toplevel():
    game_screen = tk.Toplevel(root, name="game_screen")
    game_screen.geometry("600x400")
    game_screen.title("Toplevel")
    info_label = tk.Label(game_screen, text="", name="info_label")
    info_label.pack()
    main_frame = tk.Frame(game_screen, name="main_frame")
    main_frame.pack()
    new_items1(main_frame) # create welcome text in the main frame

menu = tk.Canvas(root, width=600, height=400, bg="black")
menu.pack(fill=tk.BOTH, expand=True)
button = tk.Button(menu, text="START", width=10, height=2, command=ask_name, font=("Helvetica", 12), anchor=tk.S)
button.place(x=230, y=300)


# A chain of functions that remove previous window elements and create new ones.

# remove all labels and buttons in parent widget
def clear(parent):
    for i in parent.winfo_children():
        i.destroy()
        
messages = {
    0: "Text 1.0",
    1: "Text 1.1",
    2: "Text 1.2",
    3: "Text 1.3"
    }

def new_items1(parent): # parent = root.nametowidget(".game_screen.main_frame")
    score = 0
    def next_():
        nonlocal score # see Python scopes and LEGB rule
        if score == len(messages):
            new_items2(parent) # create first question in the main frame
            return
        else:
            label.config(text=messages.get(score))
            score += 1
            
    label = tk.Label(parent, text="Welcome, {}".format(name))
    label.pack()
    button = tk.Button(parent, text="NEXT", command=next_)
    button.pack()

def new_items2(parent):
    clear(parent)
    info = root.nametowidget(".game_screen.info_label")
    info.config(text="First\nDecision")
    label = tk.Label(parent, text="Do you join the tournament?")
    label.pack()
    # using a lambda to delay the execution of a function until a button is clicked
    button1 = tk.Button(parent, text="Join", command=lambda: new_items3(parent, "You decide to join the tournament"))
    button1.pack()
    button2 = tk.Button(parent, text="Leave", command=lambda: new_items3(parent, "You choose to explore the arena in search of an exit"))
    button2.pack()

def new_items3(parent, text):
    clear(parent)
    info = root.nametowidget(".game_screen.info_label")
    info.config(text="")
    label = tk.Label(parent, text=text)
    label.pack()
    button = tk.Button(parent, text="NEXT", command=lambda: new_items4(parent))
    button.pack()

def new_items4(parent):
    clear(parent)
    info = root.nametowidget(".game_screen.info_label")
    info.config(text="Second\nDecision")
    label = tk.Label(parent, text="You encounter a wise wizard")
    label.pack()
    # we can also set several functions for a single button
    button1 = tk.Button(parent, text="Listen", command=lambda: [showinfo("Ending 1/2 (Good ending)", "Good"), new_items5(parent, "Win")])
    button1.pack()
    button2 = tk.Button(parent, text="Ignore", command=lambda: [showinfo("Ending 2/2 (Bad ending)", "Bad"), new_items5(parent, "Try again")])
    button2.pack()

def new_items5(parent, text):
    clear(parent)
    info = root.nametowidget(".game_screen.info_label")
    info.config(text="")
    label = tk.Label(parent, text=text)
    label.pack()
    button = tk.Button(parent, text="EXIT", command=end)
    button.pack()

def end():
    root.nametowidget(".game_screen").destroy()
    root.deiconify()

# As a rule, there should be only one event loop (the root window mainloop).   
root.mainloop()
Sign up to request clarification or add additional context in comments.

1 Comment

Thankyou so much, i integrated the changes!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.