1

I am trying to make a graphical slot machine and am currently working on trying to make the slots "spin". However the buttons seem to skip all other changes and go straight to the final value. I have tried using time.sleep but this too doesn't work. Currently I am looping through a second function but still does not work. How can I ensure the buttons show all values they have taken throughout the looping process?

Here is the code below:

import tkinter as tk,random,time

root=tk.Tk()

results=["@","!","$","W","*","£","#","X","%"]

class spin:
    def __init__(self,rowa,columna,text):
        self.text=text
        self=tk.Button(root, height=1,width=2,text=text)
        self.grid(row=rowa,column=columna)

class spun:
    def __init__(self,rowa,columna,text,com):
        self.text=text
        self=tk.Button(root, height=1,width=15,text=self.text,command=com)
        self.grid(row=rowa,column=columna, columnspan=5)

def rotate():
    for i in range(0,10):
        part2()
        time.sleep(0.00005)


def part2():
    global slot1,slot2,slot3,slot4,slot5
    slot1=spin(1,0,results[random.randint(0,len(results)-1)])
    slot2=spin(1,1,results[random.randint(0,len(results)-1)])
    slot3=spin(1,2,results[random.randint(0,len(results)-1)])
    slot4=spin(1,3,results[random.randint(0,len(results)-1)])
    slot5=spin(1,4,results[random.randint(0,len(results)-1)])




slot1=spin(1,0,"@")
slot2=spin(1,1,"£")
slot3=spin(1,2,"%")
slot4=spin(1,3,"$")
slot5=spin(1,4,"#")

spinner=spun(2,0,"Spin",rotate)

root.mainloop()
Xucas
  • 21
  • 1
  • 3
  • Your rotate() function runs and completes without affecting anything. Then it returns to tkinter which only sees the last state. You need to investigate after(). – quamrana Feb 13 '20 at 09:21
  • Add `root.update_idletasks()` at the end of `part2()`. Also don't recreate the buttons, just update their text. Do not assign to `self` in `spin.__init__()` (and also `spun`), use an instance variable instead. – acw1668 Feb 13 '20 at 09:38
  • First you have to understand [Event-driven programming](https://stackoverflow.com/a/9343402/7414759) – stovfl Feb 13 '20 at 11:20

1 Answers1

0

As stated in the comments, the key is to use update_idletasks() in the for loop to force the GUI to update at each iteration.

Below is a suggestion about how to structure your code. Instead of using global slot1, ... you could create a class for your slot machine. As indicated in the comments you don't need to recreate the buttons at each iteration in rotate(), you just need to change their texts with .configure(text=<new value>). Finally I used random.choices() to directly draw a random value in a list instead of drawing the item's index with random.randint().

import tkinter as tk
import random


class Spinner(tk.Frame):
    def __init__(self, master, results, **kw):
        tk.Frame.__init__(self, master, **kw)
        self.results = results

        self.slots = []
        for i in range(5):
            b = tk.Button(self, height=1, width=2, text=self.results[i])
            b.grid(row=0, column=i)
            self.slots.append(b)

        tk.Button(self, height=1, width=15, text='Spin',
                  command=self.rotate).grid(row=1, columnspan=5)

    def rotate(self):
        for i in range(0, 10):
            for slot in self.slots:
                slot.configure(text=random.choices(self.results))
            self.update_idletasks()  # force GUI to update
            self.after(5)  # tkinter method which pause the GUI, the time is given in ms
                           # it can also be use to schedule a function call (see Tkinter doc)


root = tk.Tk()
results = ["@", "!", "$", "W", "*", "£", "#", "X", "%"]

spinner = Spinner(root, results)
spinner.pack()

root.mainloop()

Note: you might want to have a look at the style guideline PEP 8 which helps writing clear python code (e.g. they advise to capitalize class names, put one space after a comma, ...)

j_4321
  • 15,431
  • 3
  • 34
  • 61