dfreeze
dfreeze

Reputation: 685

How do I wait for a certain number of buttons to be clicked in Tkinter/Python?

I'm trying to write a simple 'Simon' game, but I have hit a road block here, and honestly have no idea how to get around it.

So here, I made a class for the four buttons in the GUI:

class button:
    def buttonclicked(self):
            self.butclicked= True

    def checkIfClicked(self):
            if self.butclicked== True:
                    global pressed
                    pressed.append(self.color)
                    self.butclicked= False

    def __init__(self, color1):
            self.color= color1
        self.button= tk.Button(root, text=' '*10, bg= self.color, command= self.buttonclicked)
        self.button.pack(side='left')
        self.butclicked=False

I then created four instances of this class in blue, red, yellow, and green as bb, rb, yb, and gb.

Once everything is packed into the Tk() module, it enters a while loop that appends a random color to a list activecolors. I try to use the following loop to wait until the list pressed is at least as long as the list activecolors before comparing the two to see if the user was correct:

while len(pressed)<len(activecolors):
                    sleep(.25)
                    print('In the check loop')
                    bb.checkIfClicked()
                    rb.checkIfClicked()
                    yb.checkIfClicked()
                    gb.checkIfClicked()

However, since it is stuck inside the while loop, the program can't tell that the button has been clicked. I thought adding the sleep method into the loop would allow the code to have time to do other things (such as process button clicks), but this is not the case. Any help is appreciated.

Here is the link to the full code, if you would like to see it. A warning though: it's not pretty.

Edit: I ended up just changing the code to check the list only after a new button was clicked, telling the computer the code was ready. I've updated the Google Document if you'd like to see it.

Upvotes: 1

Views: 933

Answers (1)

user2540905
user2540905

Reputation: 36

You are making it too complicated. This program uses partial from functiontools to allow a variable to be passed to the function so one function handles all clicks (Python 2.7).

from Tkinter import *
from functools import partial

class ButtonsTest:
    def __init__(self):
        self.top = Tk()
        self.top.title('Buttons Test')
        self.top_frame = Frame(self.top, width =400, height=400)
        self.colors = ("red", "green", "blue", "yellow")
        self.colors_selected = []
        self.num_clicks = 0
        self.wait_for_number = 5
        self.buttons()
        self.top_frame.grid(row=0, column=1)

        Button(self.top_frame, text='Exit', 
         command=self.top.quit).grid(row=2,column=1, columnspan=5)

        self.top.mainloop()

    ##-------------------------------------------------------------------         
    def buttons(self):
        for but_num in range(4):
            b = Button(self.top_frame, text = str(but_num+1), 
                  command=partial(self.cb_handler, but_num))
            b.grid(row=1, column=but_num+1)

    ##----------------------------------------------------------------
    def cb_handler( self, cb_number ):
        print "\ncb_handler", cb_number
        self.num_clicks += 1
        this_color = self.colors[cb_number]
        if (self.num_clicks > self.wait_for_number) \
             and (this_color in self.colors_selected):
            print "%s already selected" % (this_color)
        self.colors_selected.append(this_color)

##===================================================================
BT=ButtonsTest()

Upvotes: 1

Related Questions