是否有一种方法可以在Tkinter中打开另一个GUI,播放Gif,而主GUI仍然处于活动状态



我一周前才开始学习Python,目前正在学习Tkinter。我想编写一款《TicTacToe》游戏,它会打开另一个GUI,每当有人获胜时就会播放一个Gif。TicTacToe可以工作,尽管它可能需要更多的代码行才能完美。我可以通过root1 = tk.Toplayer()打开另一个GUI,它应该播放Gif。当它打开时,它播放Gif,但只有一次。有可能使它成为一个真正的循环Gif吗?

下面是我的代码:

import tkinter as tk
from PIL import Image, ImageTk, ImageSequence
import time

clicked = True
count = 0
winner = False
def b_check(b1, b2, b3, b4, b5, b6, b7, b8, b9):
global winner
winner = False
if b1["bg"] == "red" and b2["bg"] == "red" and b3["bg"] == "red":
print("sieg")
winner = True
win()
elif b4["bg"] == "red" and b5["bg"] == "red" and b6["bg"] == "red":
winner = True
winner = True
win()
elif b7["bg"] == "red" and b8["bg"] == "red" and b9["bg"] == "red":
winner = True
winner = True
win()
elif b1["bg"] == "red" and b4["bg"] == "red" and b7["bg"] == "red":
winner = True
winner = True
win()
elif b2["bg"] == "red" and b5["bg"] == "red" and b8["bg"] == "red":
winner = True
winner = True
win(play_gif())
elif b3["bg"] == "red" and b6["bg"] == "red" and b9["bg"] == "red":
winner = True
winner = True
win()
elif b1["bg"] == "red" and b5["bg"] == "red" and b9["bg"] == "red":
winner = True
winner = True
win()
elif b3["bg"] == "red" and b5["bg"] == "red" and b7["bg"] == "red":
winner = True
winner = True
win()
elif b1["bg"] == "green" and b2["bg"] == "green" and b3["bg"] == "green":
winner = True
winner = True
win()
elif b4["bg"] == "green" and b5["bg"] == "green" and b6["bg"] == "green":
winner = True
winner = True
win()
elif b7["bg"] == "green" and b8["bg"] == "green" and b9["bg"] == "green":
winner = True
winner = True
win()
elif b1["bg"] == "green" and b4["bg"] == "green" and b7["bg"] == "green":
winner = True
winner = True
win()
elif b2["bg"] == "green" and b5["bg"] == "green" and b8["bg"] == "green":
winner = True
winner = True
win()
elif b3["bg"] == "green" and b6["bg"] == "green" and b9["bg"] == "green":
winner = True
winner = True
win()
elif b1["bg"] == "green" and b5["bg"] == "green" and b9["bg"] == "green":
winner = True
winner = True
win()
elif b3["bg"] == "green" and b5["bg"] == "green" and b7["bg"] == "green":
winner = True
winner = True
win()

def b_switch(b):
global clicked, count
if b["state"] == "normal" and clicked == True:
b["bg"] = "red"
b["state"] = "disabled"
clicked = False
count += 1
elif b["state"] == "normal" and clicked == False:
b["bg"] = "green"
b["state"] = "disabled"
clicked = True
count += 1

def b_reset(root):
root.destroy()
mainWindow()

def mainWindow():
root = tk.Tk()
root.title("TicTacToe")
root.geometry("400x410")
root.resizable(False, False)
b0 = tk.Button(root, text="reset", height=1, width=50, command=lambda: [b_reset(root)])
b0.pack()
b1 = tk.Button(root, width=15, height=7, command=lambda: [b_switch(b1), b_check(b1, b2, b3, b4, b5, b6, b7, b8, b9),
])
b1.place(x=10, y=30)
b2 = tk.Button(root, width=15, height=7, command=lambda: [b_switch(b2), b_check(b1, b2, b3, b4, b5, b6, b7, b8, b9),
])
b2.place(x=140, y=30)
b3 = tk.Button(root, width=15, height=7, command=lambda: [b_switch(b3), b_check(b1, b2, b3, b4, b5, b6, b7, b8, b9),
])
b3.place(x=270, y=30)
b4 = tk.Button(root, width=15, height=7, command=lambda: [b_switch(b4), b_check(b1, b2, b3, b4, b5, b6, b7, b8, b9),
])
b4.place(x=10, y=160)
b5 = tk.Button(root, width=15, height=7, command=lambda: [b_switch(b5), b_check(b1, b2, b3, b4, b5, b6, b7, b8, b9),
])
b5.place(x=140, y=160)
b6 = tk.Button(root, width=15, height=7, command=lambda: [b_switch(b6), b_check(b1, b2, b3, b4, b5, b6, b7, b8, b9),
])
b6.place(x=270, y=160)
b7 = tk.Button(root, width=15, height=7, command=lambda: [b_switch(b7), b_check(b1, b2, b3, b4, b5, b6, b7, b8, b9),
])
b7.place(x=10, y=290)
b8 = tk.Button(root, width=15, height=7, command=lambda: [b_switch(b8), b_check(b1, b2, b3, b4, b5, b6, b7, b8, b9),
])
b8.place(x=140, y=290)
b9 = tk.Button(root, width=15, height=7, command=lambda: [b_switch(b9), b_check(b1, b2, b3, b4, b5, b6, b7, b8, b9),
])
b9.place(x=270, y=290)
root.mainloop()

def win():
if winner == True:
root1 = tk.Toplevel()
root1.resizable(False, False)
root1.title("Winner")
global img
img = Image.open("capybara-ok-i-pull-up.gif")
label = tk.Label(root1)
label.place(x=0, y=0)
play_gif(root1, img, label)

def play_gif(root1, img, label):
while winner == True:
for img in ImageSequence.Iterator(img):
img = img.resize((300,300))
img = ImageTk.PhotoImage(img)
label.config(image=img)
root1.update()
time.sleep(0.01)
root1.after(0, play_gif(root1, img, label))

mainWindow()

我试着使用第二个GUI,它是root1 = tk.Tk(),它没有播放Gif,因为显然Tkinter不喜欢它,如果另一个GUI打开。然后我遇到了Toplayer命令,但现在我被上面提到的问题困住了。

如果你想在GIF中循环图像,你可以使用itertools.cycle()来创建图像的循环列表,并使用next()来获得循环列表中的下一个图像。

下面是修改后的play_gif()win():

from itertools import cycle
import tkinter as tk
from PIL import Image, ImageTk, ImageSequence
...
def play_gif(imagelist, label):
img = next(imagelist) # get next image in the list
img = img.resize((300, 300))
label.img = ImageTk.PhotoImage(img)
label.config(image=label.img)
label.after(50, play_gif, imagelist, label)
def win():
# create a cycle list of images from a GIF image
with Image.open("capybara-ok-i-pull-up.gif") as im:
imagelist = cycle(ImageSequence.all_frames(im))
root1 = tk.Toplevel()
root1.resizable(0, 0)
root1.title("Winner")
label = tk.Label(root1)
label.pack()
# start the image animation
play_gif(imagelist, label)
...

最新更新