Q:

python thread.join() hangs

I'm new to Python. I am trying to change an image on a button when it is clicked and I want the new image to render before any of the other code executes. I tried using locks and semaphores, etc and nothing was working (e.g. the do_pause function in the code below seems to execute before the image is rendered). I tried to use a separate thread, but the join() is hanging the program. It's like it's in an infinite loop, but I can't figure out why.
# Game button click event
def game_button_click(self, index):
    self.clicks += 1
    t1 = Thread(target=self.show_image, args=(index,))
    t1.start()
    t1.join()

    if self.clicks % 2 == 0 and self.uncovered % 2 == 0:
        self.moves += 1
        moves = self.MOVE_TEXT if self.moves == 1 else self.MOVES_TEXT
        self.lbl_moves.config(text=str(self.moves) + moves)
        if self.scrambled_names[self.prev_index] == self.scrambled_names[index]:
            self.uncovered += 2
        else:
            self.do_pause()
            self.buttons[self.prev_index].config(image=self.default_img,
                command=lambda myIndex=self.prev_index: self.game_button_click(myIndex))
            self.buttons[index].config(image=self.default_img,
                command=lambda myIndex=index: self.game_button_click(myIndex))
    self.prev_index = index

# function to reveal the hidden image
def show_image(self, index):
    try:
        new_img = Image.open(self.IMG_PATH + self.scrambled_names[index])
        self.game_images[index] = ImageTk.PhotoImage(new_img)
        self.buttons[index].config(image=self.game_images[index], command=self.do_nothing)
    except:
        exception = sys.exc_info()[0]
        print( "Error: %s" % exception)

# function to create pause
def do_pause(self):
    event = Event()
    event.wait(timeout=self.PAUSE)

A:

Figured out a fix (not really sure why it works). I moved everything after t1.join() in the game_button_click event to a different method called check_for_match. Then I changed the code in the game_button_click event. The do_pause and show_image code pretty much remained the same. Like I said, not sure why it works, but it does. Here is the new code:
# Game button click event
def game_button_click(self, index):
    lock = Lock()
    with lock:
        self.show_image(index)

    t = Thread(target=self.check_for_match, args=(index,))
    t.start()

# function to check for matches
def check_for_match(self, index):
    self.clicks += 1
    if self.clicks % 2 == 0 and self.uncovered % 2 == 0:
        self.moves += 1
        moves = self.MOVE_TEXT if self.moves == 1 else self.MOVES_TEXT
        self.lbl_moves.config(text=str(self.moves) + moves)
        if self.scrambled_names[self.prev_index] == self.scrambled_names[index]:
            self.uncovered += 2
        else:
            self.do_pause()
            self.buttons[self.prev_index].config(image=self.default_img,
                command=lambda myIndex=self.prev_index: self.game_button_click(myIndex))
            self.buttons[index].config(image=self.default_img,
                command=lambda myIndex=index: self.game_button_click(myIndex))
    self.prev_index = index

