我目前正在構建一個tkinter應用程式。其核心概念是用戶必須點擊方塊。
就像你在圖片中看到的那樣,我們有一個方格,用戶可以從中選擇一些方格。通過點擊它們,用戶應該看到一個小影片,就像你在GIF中看到的那樣。
問題
在這個GIF中,你可以看到問題所在。我的解決方案使用python的multiprocessing模塊。但似乎因為我在影片制作程序中開了很多執行緒,所以可視化的速度變慢了,并停止了我希望的功能。
我的嘗試很簡單:
process = Process(target=self.anim,args=("someargs",)
process.run()
是否有辦法將這些影片捆綁在一個行程中,避免許多執行緒,或者python/tkinter沒有提供任何方法來解決我的問題?
謝謝你的幫助。
uj5u.com熱心網友回復:
試試這個:
import tkinter as tk
# Patially taken from: https://stackoverflow.com/a/17985217/11106801
def create_circle(self, x: int, y:int, r:int, **kwargs) -> int。
return self.create_oval(x-r, y-r, x r, y r, **kwargs)
def resize_circle(self, id: int, x:int, y:int, r:int) -> None:
self.coords(id, x-r, y-r, x r, y r)
tk.Canvas.create_circle = create_circle
tk.Canvas.resize_circle = resize_circle
# Defining constants: 定義常數
WIDTH:int =400
高度:int = 400。
SQUARES_WIDTH:int =40
SQUARES_HEIGHT:int = 40。
# 每個方塊將是它自己的類,以使其更容易操作。
class Square。
# 這可能會給不知道`__slots__的人帶來麻煩。
# __slots__ = ("canvas", "id", "x", "y", "fill")
def __init__(self, canvas:tk.Canvas, x:int, y:int) 。
self.canvas:tk.Canvas = canvas
self.x:int = x
self.y:int = y
self.id:int = None。
self.filled:bool = False。
def fill(self, for_loop_counter:int=0) -> None:
""
這實作了一個tkinter友好的for回圈,延遲為
10毫秒。它創建了一個`半徑=20'的圓。
"""
# If the square is already filled jsut return[/span].
if self.fill:
return None
x:int = self.x SQUARES_WIDTH //2
y:int = self.y SQUARES_WIDTH //2
# 如果這是第一次,創建圓。
if for_loop_counter == 0:
self.id:int = self.canvas. create_circle(x, y, 0, outline="", fill="black")
# Grow the cicle[/span]。
else:
self.canvas.resize_circle(self.id, x, y, for_loop_counter)
# 如果我們達到最高半徑:
if for_loop_counter == 20:
self.fill_square()
# 否則在10毫秒內呼叫`self.fill`與。
# `for_loop_counter 1`作為引數。
else:
self.canvas.after(10, self.fill, for_loop_counter 1)
def fill_square(self) -> None:
""
移除圓圈并填入正方形
""
self.canvas.delete(self.id)
x2:int = self.x SQUARES_WIDTH
y2:int = self.y SQUARES_HEIGHT
self.id = self.canvas.create_rectangle(self.x, self.y, x2, y2, fill="black", outline="" /span>)
self.filled:bool = True。
class App。
# This can cause problems for people that don't know `__slots__`.
# __slots__ = ("root", "canvas", "squares")。
def __init__(self):
self.root:tk.Tk = tk.Tk()
self.canvas:tk.Canvas = tk.Canvas(self.root, width=WIDTH, height=HEIGHT)
self.canvas.pack()
# 創建方塊:.
self.squares:list[Square] = [] 。
for x in range(0, WIDTH, SQUARES_WIDTH):
for y in range(0, HEIGHT, SQUARES_HEIGHT):
square:square = Square(self.canvas, x, y)
self.squares.append(square)
self.canvas.bind("<Button-1>", self.on_mouse_clicked)
self.canvas.bind("<B1-Motion>", self.on_mouse_clicked)
def on_mouse_clicked(self, event:tk.Event) -> None:
# 搜索被按下的方塊。
mouse_x:int = event.x
mouse_y:int=event.y
for square in self.squares。
if 0 < mouse_x - square.x < SQUARES_WIDTH:
if 0 < mouse_y - square.y < SQUARES_HEIGHT:
# 告訴那個方塊,它應該填充自己。
square.fill()
return None
def mainloop(self) -> None:
self.root.mainloop()
if __name__ == "__main__"/span>:
app = App()
app.mainloop()
這實作了一個tkinter友好的for回圈,它每隔10毫秒調度對<Square>.fill的呼叫,直到半徑為20。然后它就會填滿整個正方形。
要測驗該代碼,只需按下視窗的任何位置。你也可以在周圍拖動滑鼠。
對于清除方塊也是如此:
import tkinter as tk
# Patially taken from: https://stackoverflow.com/a/17985217/11106801
def create_circle(self, x: int, y:int, r:int, **kwargs) -> int:
return self.create_oval(x-r, y-r, x r, y r, **kwargs)
def resize_circle(self, id: int, x:int, y:int, r:int) -> None:
self.coords(id, x-r, y-r, x r, y r)
tk.Canvas.create_circle = create_circle
tk.Canvas.resize_circle = resize_circle
# Defining constants: 定義常數
WIDTH:int =400
高度:int = 400。
SQUARES_WIDTH:int =40
SQUARES_HEIGHT:int = 40。
# 每個方塊將是它自己的類,以使其更容易操作。
class Square。
# 這可能會給不知道`__slots__的人帶來麻煩。
# __slots__ = ("canvas", "id", "x", "y", "fill")
def __init__(self, canvas:tk.Canvas, x:int, y:int) 。
self.canvas:tk.Canvas = canvas
self.x:int = x
self.y:int = y
self.id:int = None。
self.filled:bool = False。
def fill(self, for_loop_counter:int=0) -> None:
""
這實作了一個tkinter友好的for回圈,延遲為
10毫秒。它創建了一個`半徑=20'的圓。
"""
x:int = self.x SQUARES_WIDTH // 2.
y:int = self.y SQUARES_WIDTH //2
# 如果這是第一次,創建圓。
if for_loop_counter == 0:
# If the square is already filled just return.
if self.fill:
return None
self.fill:bool = True
self.id:int = self.canvas。 create_circle(x, y, 0, outline="", fill="black")
# 用戶要清除這個方塊。
elif self.id is None:
return None:
# Grow the cicle。
else:
self.canvas.resize_circle(self.id, x, y, for_loop_counter)
# 如果我們達到最高半徑:
if for_loop_counter == 20:
self.fill_square()
# 否則在10毫秒內呼叫`self.fill`與。
# `for_loop_counter 1`作為引數。
else:
self.canvas.after(10, self.fill, for_loop_counter 1)
def fill_square(self) -> None:
""
移除圓圈并填入正方形
""
x2:int = self.x SQUARES_WIDTH
y2:int = self.y SQUARES_HEIGHT
self.canvas.delete(self.id)
self.id = self.canvas.create_rectangle(self.x, self.y, x2, y2, fill="black", outline="" /span>)
def clear(self) -> None:
""
清除方塊
""
self.filled:bool = False。
self.canvas.delete(self.id)
self.id:int = None。
class App。
# 這可能會給不知道`__slots__的人帶來問題。
__slots__ = ("root", "canvas", "quares")
def __init__(self)。
self.root:tk.Tk = tk.Tk()
self.canvas:tk.Canvas = tk.Canvas(self.root, width=WIDTH, height=HEIGHT)
self.canvas.pack()
# 創建方塊:.
self.squares:list[Square] = [] 。
for x in range(0, WIDTH, SQUARES_WIDTH):
for y in range(0, HEIGHT, SQUARES_HEIGHT):
square:square = Square(self.canvas, x, y)
self.squares.append(square)
self.canvas.bind("<Button-1>", self.on_mouse_clicked)
self.canvas.bind("<B1-Motion>", self.on_mouse_clicked)
self.canvas.bind("<Button-3>", self.on_mouse_clicked)
self.canvas.bind("<B3-Motion>", self.on_mouse_clicked)
def on_mouse_clicked(self, event:tk.Event) -> None:
# 搜索被按下的方塊。
mouse_x:int = event.x
mouse_y:int=event.y
for square in self.squares。
if 0 < mouse_x - square.x < SQUARES_WIDTH:
if 0 < mouse_y - square.y < SQUARES_HEIGHT:
# 如果滑鼠右鍵被按下
if (event.state & 1024 != 0) or (event.num == 3) 。
# 告訴那個廣場,它應該清除自己。
square.clear()
else:
# 告訴該方塊它應該填充自己。
square.fill()
return None
def mainloop(self) -> None:
self.root.mainloop()
if __name__ == "__main__"/span>:
app = App()
app.mainloop()
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/319400.html
標籤:
下一篇:使用JDK16.0.2、JavaEE8.0.1、TomCat9.0.52、Vaadin14.6.8,無法讓helloworld型別的程式作業。


