Python Forum
dice roller with tkinter
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
dice roller with tkinter
#1
i am using tkinter to make my dice roller code look more appealing. i have gotten tkinter to display a roll button that works on the shell but in the same tkinter window it displays one value under roll and wonbt change that number when i click roll. how do i get it to change the number every time i click roll. Wall im stumped

import tkinter as tk
import random
die_1 = random. randint(1,6)
die_2 = random. randint(1,6)
total = float(die_1) + float(die_2)

class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.pack()
        self.create_widgets()

    def create_widgets(self):
        self.button = tk.Button(self)
        self.button["text"] = "Roll"
        self.button["command"] = self.roll
        self.button.pack(side="top")

        self.result = tk.Label(self)
        self.result["text"] = total
        self.result.pack(side="bottom")

    def roll(self):        
        die_1 = random. randint(1,6)
        die_2 = random. randint(1,6)
        total = float(die_1) + float(die_2)
        print(int(total))

root = tk.Tk()
app = Application(master=root)
app.mainloop()
Larz60+ write May-25-2023, 11:55 AM:
Please post all code, output and errors (it it's entirety) between their respective tags. Refer to BBCode help topic on how to post. Use the "Preview Post" button to make sure the code is presented as you expect before hitting the "Post Reply/Thread" button.
I fixed your code this time. Please use BBCode tags on future posts.
Reply
#2
I think you are missing an opportunity. Buttons can display images, like the face of a die. Why not make a die that you roll by click it and then change the image to reflect the value of the roll.
Reply
#3
(Sep-02-2020, 08:12 PM)deanhystad Wrote: I think you are missing an opportunity. Buttons can display images, like the face of a die. Why not make a die that you roll by click it and then change the image to reflect the value of the roll.

not to be rude but
i would appreciate not being told that i could be doing something not related to my question differently, i may do it in the future but i just want to know how to get past a specific problem
Reply
#4
Look at tkinter StringVar (or IntVar) for the label. After reading about that the answer should be obvious.

Why are you doing the float conversion and then later the conversion back to int? die 1 and die2 are ints. Can't you add ints?
die_1 = random. randint(1,6)
die_2 = random. randint(1,6)
total = float(die_1) + float(die_2)
print(int(total))
And why does this code appear twice? Why is there die rolling code at the top of the program? A leftover perhaps?
Reply
#5
(Sep-02-2020, 10:54 PM)deanhystad Wrote: Look at tkinter StringVar (or IntVar) for the label. After reading about that the answer should be obvious.

Why are you doing the float conversion and then later the conversion back to int? die 1 and die2 are ints. Can't you add ints?
die_1 = random. randint(1,6)
die_2 = random. randint(1,6)
total = float(die_1) + float(die_2)
print(int(total))
And why does this code appear twice? Why is there die rolling code at the top of the program? A leftover perhaps?
i am still very confused, can you just tell me what i should do yo my code to make it work
Reply
#6
I stumbled upon this thread from three years ago, and it seems like you were trying to make your dice roller code more appealing using Tkinter. Nice choice!

In your current code, it looks like the total variable is defined outside the roll function, which means it won't update dynamically. To fix this, you'll want to move the lines where you roll the dice and calculate the total inside the roll function itself. That way, each time you click the roll button, the values will be freshly generated.
To update the displayed number, you can use the configure method on the self.result label. Within the roll function, add self.result.configure(text=total) to ensure the label reflects the newly rolled total.
Oh, and by the way, if you're looking for some inspiration or additional guidance, you can always check out FlipSimu's dice roller. They have a fantastic tool that might provide some useful insights.
Reply
#7
Refactoring service ...

import random
import tkinter as tk


def roll_dice(n):
    return tuple(random.randint(1, 6) for _ in range(n))


# inheritance, so the instance of Application is a Frame
class Application(tk.Frame):
    def __init__(self, master=None):
        # calling super to initialize the Frame
        # so __init__ is called on tk.Frame
        super().__init__(master)

        # 3 IntVars, where value is initialized as empty str
        # the first argument is the master, in this case the frame instance
        self.total = tk.IntVar(self, "")
        self.left_dice = tk.IntVar(self, "")
        self.right_dice = tk.IntVar(self, "")
        self.create_widgets()

    def create_widgets(self):
        descriptions = ("Total:", "Dice 1:", "Dice 2:")
        variables = (self.total, self.left_dice, self.right_dice)

        # zip returns a zip_iterator, which yields tuples
        # enumerate takes this tuples and yields index, tuple
        # enumerate starts by default with 0 and counts 1 up per element
        # to unpack this structure, parenthesis are used
        for row, (text, variable) in enumerate(zip(descriptions, variables)):
            # no references required yet
            # variable sets the text of Label
            tk.Label(self, text=text).grid(row=row, column=0)
            tk.Label(self, textvariable=variable).grid(row=row, column=1)

        # the names row, text and variable
        # do not disappear

        # row is the last row from for-loop
        # adding 1 to it for the next row
        row += 1

        tk.Button(self, text="Roll", command=self.roll).grid(row=row, column=0)
        tk.Button(self, text="Quit", command=self.master.destroy).grid(
            row=row, column=1
        )

    def roll(self):
        # roll_dice(2) returns a tuple with two integers
        dices = roll_dice(2)

        # set the variables, which affects the text on the labels
        self.left_dice.set(dices[0])
        self.right_dice.set(dices[1])
        # sum(dices) -> total
        self.total.set(sum(dices))


if __name__ == "__main__":
    # this branch is only executed, if you run this program directly
    # is this module is imported, this branch does not run
    # this makes it possible to reuse the class in other modules

    root = tk.Tk()
    app = Application(master=root)
    # if the Frame is inside a grid, you can't use pack()
    # I removed this from the __init__ method
    # so you have to call pack/grid on the instance
    app.pack()

    # instead of indirection, the Tk instance
    # is directly used to run the mainloop
    root.mainloop()

    # before
    # app.mainloop()
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020