my program should after click roll dice - it use six images of dice, with one, two, three, four, five and six dots. First is showed image with one dot and than after click on the image should randomly change 8 times. In the end, last random image should stay on screen, but it doesn't work and I am not able to solve it. Any idea how to fix it please? (I know that 3 classes are not necessary for this, but i will continue in it when I'll have soluted this problem) Thanks
import tkinter, random
class Main:
def __init__(self, area, dice):
dice.throw(area)
class Area:
def __init__(self):
self.canvas = tkinter.Canvas(width=1000, height=600)
self.canvas.pack()
self.dice1 = tkinter.PhotoImage(file='numberOne.png')
self.canvas.create_image(680,540,image=self.dice1)
self.canvas.bind('<Button-1>', Dice.throw)
class Dice:
def throw(event):
if event.x < 730 and event.x > 630 and event.y < 590 and event.y > 490:
dice1 = tkinter.PhotoImage(file='numberOne.png')
dice2 = tkinter.PhotoImage(file='numberTwo.png')
dice3 = tkinter.PhotoImage(file='numberThree.png')
dice4 = tkinter.PhotoImage(file='numberFour.png')
dice5 = tkinter.PhotoImage(file='numberFive.png')
dice6 = tkinter.PhotoImage(file='numberSix.png')
for i in range(8):
number = random.randrange(6) + 1
if number == 1:
area.canvas.create_image(680,540,image=dice1)
elif number == 2:
area.canvas.create_image(680,540,image=dice2)
elif number == 3:
area.canvas.create_image(680,540,image=dice3)
elif number == 4:
area.canvas.create_image(680,540,image=dice4)
elif number == 5:
area.canvas.create_image(680,540,image=dice5)
elif number == 6:
area.canvas.create_image(680,540,image=dice6)
area.canvas.after(100)
area.canvas.update()
pl = Area()
dice = Dice()
main = Main(pl, dice)
Problem is that Area
instance (pl
) need access to Dice
instance (dice
) and Dice
instance needs access to Area
instance.
dice = Dice(root)
area = Area(root, dice) # `Area` gets access to `Dice` instace
dice.area = area # `Dive` gets access to `Area` instace
after that Dice
can use dice.throw
and Dice
can use area.canvas
or other elements.
To make it simpler I assign tag to image on canvas and then I can use tag_bind
to assign <Button-1>
and I don't have to check event.x
, event.y
.
Instead of creating new image with create_image
I change image in existing element on cavas.
create_image()
gives element ID
self.image_id = self.canvas.create_image(...)
so later I can change image in this element
self.canvas.itemconfig(self.image_id, image=image)
I keep all images on list so I don't need all variables dice1
, dice2
, etc. and I can get image using index instead of if/elif
. I can also use random.choice(self.images)
to get random element from list.
image = random.choice(self.images)
Full code:
import tkinter
import random
class Main:
def __init__(self, area, dice):
dice.throw(area)
class Area:
def __init__(self, master, dice):
self.master = master
self.canvas = tkinter.Canvas(master, width=1000, height=600)
self.canvas.pack()
self.image = tkinter.PhotoImage(file='numberOne.png')
self.image_id = self.canvas.create_image(680, 540, image=self.image, tags='tag_image')
self.canvas.tag_bind('tag_image', '<Button-1>', dice.throw)
def change_image(self, image):
print('changing image')
self.canvas.itemconfig(self.image_id, image=image)
class Dice:
def __init__(self, master):
self.master = master
self.area = None # assign later
self.images = [
tkinter.PhotoImage(file='numberOne.png')
tkinter.PhotoImage(file='numberTwo.png')
tkinter.PhotoImage(file='numberThree.png')
tkinter.PhotoImage(file='numberFour.png')
tkinter.PhotoImage(file='numberFive.png')
tkinter.PhotoImage(file='numberSix.png')
]
def throw(self, event):
if self.area:
for i in range(8):
image = random.choice(self.images)
self.area.change_image(image)
self.master.update()
self.master.after(100)
# --- main ---
root = tkinter.Tk()
dice = Dice(root)
area = Area(root, dice)
dice.area = area
root.mainloop()