0

I'm new to GUIs and just learning how to use Tkinter. I wrote a python program to put the students in my class into pairs for my seating charts. The program itself runs fine; the problem is the tkinter gui. I've tried to make the button generate and display a new set of pairs each time. Instead, the GUI will display the first set of pairs as soon as I open it, without even pressing the button. The button does nothing. If I run it in console, I don't get any error messages or anything printed to console.

At Button commands in Tkinter I saw an answer to do with using lambda. When I tried it, the label will initially be blank. It will display the pairs when the button is pressed the first time, as expected, but on subsequent presses it just makes the label blank again.

I'm not sure what the problem is. Can you help me? Here is the code:

from Tkinter import *
from SeatingChart import *



root = Tk() 

class App:

    def __init__(self, master):
        self.win = Frame(master)
        self.win.pack()
        self.d = Label(self.win, text = "", width=140)
        self.d.pack()
        self.b = Button(self.win, text="Pair Up!", command=self.display_pairs(roster))
        self.b.pack()

    def display_pairs(self, l):
        self.d.config(text=pair(roster))


app = App(root)

mainloop()
Community
  • 1
  • 1

1 Answers1

0

When creating the button, the command that you supply is the result of the display_pairs method (which is None because it doesn't return anything) rather than a reference to the method.

Try:

class App:

    def __init__(self, master):
        self.win = Frame(master)
        self.win.pack()
        self.d = Label(self.win, text = "", width=140)
        # Maybe display an initial roster?
        # self.d = Label(self.win, text = pair(roster), width=140)
        self.d.pack()
        self.b = Button(self.win, text="Pair Up!", command=self.display_pairs)
        self.b.pack()

    def display_pairs(self):
        self.d.config(text=pair(roster))
Roland Smith
  • 42,427
  • 3
  • 64
  • 94
  • Thanks. I tried that, but then I get this: TypeError: display_pairs() takes exactly 2 arguments (1 given) – Celeste Sinclair May 05 '16 at 16:05
  • Did you modify the `display_pairs` method as I showed? I removed the `l` parameter since it isn't used. – Roland Smith May 05 '16 at 16:13
  • Now I have. It's doing the same thing it did when I tried the lambda thing: it will initially display a result, and then go blank on subsequent button presses. – Celeste Sinclair May 05 '16 at 16:35
  • Except for the `pair(roster)` I've tested my code and it works. Make sure that `pair(roster)` actually returns a text if you call it multiple times... – Roland Smith May 05 '16 at 16:59
  • You're absolutely right! When I run it multiple times it gives different results, but if I call it more than once it only works the one time. I"ll figure out how to fix it later when I have more time. At least now I know the GUI works. Thank you for your time! – Celeste Sinclair May 06 '16 at 03:46
  • Ok, it works now. The problem was that I was running a while loop based on the length of the roster, and deleting an item from the roster every time I added another person to pairs. As you may imagine, this resulted in the roster being empty on the second call. I made a copy of the roster and used that for my while loop, and now it works. Thanks again! – Celeste Sinclair May 06 '16 at 04:14
  • We've all made the same mistake. :-) It actually is a valuable lesson. In general it is a good idea to write functions without side effects if you can. These so-called [pure functions](https://en.wikipedia.org/wiki/Pure_function) *read* their arguments and return values, but they don't *modify* their arguments. The benefits are that it prevents surprises and that such functions are easy to test. Note that it isn't always possible to write pure functions, and one shouldn't be too hung up about it. – Roland Smith May 06 '16 at 09:17
  • I'll keep that in mind. Thanks! – Celeste Sinclair May 06 '16 at 11:00