0

I went through the topics here at stack overflow, but could not understand anything. (yes, I've seen that the answer has been answered, but really couldnt understand.)

So, here's the thing. I'm building small application that will pair couples from a group for a tournament we're having. I successfully built the algorithm that pair the players, and I've decided to make this a bit more approachable to everyone and started looking at ktinker.

I've managed to get my application to show something like this:

Title
info
info
info
info
info
Button

The button suppose to re-run the whole thing (next round) and it works. I've managed to get it with the appropriate title, and even added a new button at the end of the screen. the only problem I'm having is that I want to get rid of all the text above. destroy it and just draw on a new page.

Now, the code:

from tkinter import *

root = Tk()

root.title("Tournament")
root.geomerty("50x180")

app = Frame(root)
app.grid()

run_application() # my pairings 
#inside the code i'm pairing the players and then:
for players in player_paired:
    label=Label(app, text=players[0]+' vs. '+players[1] # its a tuple
    label.grid()
button=Button(app,text="Next Round", command=run_application)
button.grid()

#end of run_application

root.mainloop()

So, I've tried adding to the beginning of my "run_application" the next rows:

app.destroy()
app = Frame(root)
app.grid()

and got "UnboundLocalError: local variable 'app' referenced before assignment"

Would anyone help? i can't figure this out. (If able to write example, it would help a lot)

Ofek.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Ofek Ortal
  • 27
  • 1
  • 1
  • 7
  • No, I can't use run_application(app) because when i declare the button "button=Button(app,text="Next Round", command=run_application)" and adding (app) it automatically runs it, which ends up with endless recursion. so, this is not the solution here. – Ofek Ortal Sep 27 '16 at 14:22
  • I'm not sure you've read the duplicate. That's not what it suggests. You have the same error, and the same problem, and the same solution will work. – jonrsharpe Sep 27 '16 at 14:23
  • I think I did. the scope in python would not allow me to "destroy" app before I declare it inside the function. Now, if I want to call the function with "app" as an argument, It ends with endless recursion. – Ofek Ortal Sep 27 '16 at 14:25
  • I am more and more certain you didn't. Passing the variable as an argument isn't recommended by *any* of the answers, as far as I can see. – jonrsharpe Sep 27 '16 at 14:26
  • Turned out I was ignorant, rude and mostly stupid. Thank you for making me look again and again. I will remember this lesson. – Ofek Ortal Sep 27 '16 at 14:28
  • Why do you want to destroy the Frame? Instead, keep a list of the Labels, and when you want to display a new table, destroy the old Labels & populate the Frame with a new set of Labels. If the number of Labels is fixed, another option is to simply modify the texts of the existing Labels. – PM 2Ring Sep 27 '16 at 14:29

2 Answers2

1

The simplest solution is to put everything you want to destroy in a frame, and then you can simply destroy and recreate the frame, or destroy all of the children in the frame.

In your specific case, make the parent of button be root, and then you can destroy and recreate the contents of app each time you press the button.

Here is an example. I took the liberty of switching the way you're importing, to be PEP8 compliant:

import tkinter as tk
from random import shuffle

participants = [
    "Fred Flintstone", "Barney Rubble", "Wilma Flintstone", "Betty Rubble"
]

def get_pairings():
    '''for simulation purposes, this simply randomizes the participants'''
    global participants

    # see http://stackoverflow.com/a/23286332/7432
    shuffle(participants)
    return zip(*[iter(participants)]*2)


def reset():
    '''Reset the list of participants'''
    for child in app.winfo_children():
        child.destroy()

    for players in get_pairings():
        label = tk.Label(app, text="%s vs. %s" % players)
        label.grid()

root = tk.Tk()

root.title("Tournament")

app = tk.Frame(root)
app.grid()

button=tk.Button(root,text="Next Round", command=reset)
button.grid()

# this sets up the first round
reset()

root.mainloop()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
0

In my experience, I found it easier to delete the elements. Here is something you can do. I don't honestly have much time, so I will use examples from my code, instead of editing your code.

So for your labels you could do this.

labels = []
for players in player_paired:
    label=Label(app, text=players[0]+' vs. '+players[1] # its a tuple
    label.grid()
    labels.append(label)

Then to remove the text have a method that does something like this.

for label in labels:
        label.destroy()

And then go back to the start after that.

Muamer Bektić
  • 299
  • 3
  • 16