【问题标题】:How to get multiple ovals moving around the canvas?如何让多个椭圆在画布上移动?
【发布时间】:2013-07-17 07:52:06
【问题描述】:

我的问题是如何让多个带有随机数的“气泡”在屏幕上移动?

我必须做一堆 def bubble(): 还是有更简单的方法来做?在画布上随机移动“气泡”也让我感到困惑。

到目前为止的编码:

from tkinter import *
import random

def quit():
    root.destroy()


def bubble():
    xval = random.randint(5,765)
    yval = random.randint(5,615)
    canvas.create_oval(xval,yval,xval+30,yval+30, fill="#00ffff",outline="#00bfff",width=5)
    canvas.create_text(xval+15,yval+15,text=number)
    canvas.update()

def main():
    global root
    global tkinter
    global canvas
    root = Tk()
    root.title("Math Bubbles")
    Button(root, text="Quit", width=8, command=quit).pack()
    Button(root, text="Start", width=8, command=bubble).pack()
    canvas = Canvas(root, width=800, height=650, bg = '#afeeee')
    canvas.pack()
    root.mainloop()

# Create a sequence of numbers to choose from. CAPS denotes a constant variable
NUMBERS = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)

# Pick numbers randomly from the sequence with the help of a random.choice function
number = random.choice(NUMBERS)

# Create a variable to use later to see if the guess is correct
correct = number

main()

【问题讨论】:

    标签: python-3.x tkinter


    【解决方案1】:

    这应该可以帮助您:

    import Tkinter, random
    
    class BubbleFrame:
    
        def __init__(self, root):
            root.title("Math Bubbles")
            Tkinter.Button(root, text="Add Bubbles", width=8, command=self.bubble).pack()
            Tkinter.Button(root, text="Quit", width=8, command=quit).pack()
            self.canvas = Tkinter.Canvas(root, width=800, height=650, bg = '#afeeee')
            self.canvas.pack()
            self.bubbles = {} # this will hold bubbles ids, positions and velocities
    
        def bubble(self):
            # add bubbles for numbers from 1 to 20
            for number in range(1, 20+1):
                xval = random.randint(5,765)
                yval = random.randint(5,615)
                s1 = self.canvas.create_oval(xval,yval,xval+30,yval+30, fill="#00ffff",outline="#00bfff",width=5)
                s2 = self.canvas.create_text(xval+15,yval+15, text=number)
                self.bubbles[(s1, s2)] = (xval, yval, 0, 0) # add bubbles to dictionary
    
        def loop(self, root):
            for (s1, s2), (x, y, dx, dy) in self.bubbles.items():
                # update velocities and positions
                dx += random.randint(-1, 1)
                dy += random.randint(-1, 1)
                # dx and dy should not be too large
                dx, dy = max(-5, min(dx, 5)), max(-5, min(dy, 5))
                # bounce off walls
                if not 0 < x < 770: dx = -dx
                if not 0 < y < 620: dy = -dy
                # apply new velocities
                self.canvas.move(s1, dx, dy)
                self.canvas.move(s2, dx, dy)
                self.bubbles[(s1, s2)] = (x + dx, y + dy, dx, dy)
            # have mainloop repeat this after 100 ms
            root.after(100, self.loop, root)
    
    if __name__ == "__main__":
        root = Tkinter.Tk()
        frame = BubbleFrame(root)
        frame.loop(root)
        root.mainloop()
    

    请注意,我已经对代码进行了一些重组,使用一个类来包装这些方法和属性,但这完全取决于您。另请注意,我已使用 Python 2.7 完成此操作,因此可能需要进行一些小的修改,例如 Tkinter 包的名称。

    您不需要为要添加的每个气泡定义另一个bubble 函数——实际上您的代码已经在画布上添加了许多气泡,所以这部分没问题。棘手的一点是移动气泡。

    为此,我首先添加了 self.bubbles 字典,将气泡的 ID 及其标签(由 canvas.create... 方法返回)映射到它们当前的位置和速度。最后,loop 方法更新气泡的位置和速度并重新绘制画布。最后,此方法将使用after 方法安排下一次执行。

    【讨论】:

    • 线程为简单的动画增加了太多的复杂性。另外,这几乎肯定会意外崩溃,因为 tkinter 不是线程安全的。除了创建小部件的线程之外,您无法从任何线程可靠地调用小部件方法。
    • 正确的方法是意识到你已经在运行一个无限循环——主循环——并利用它。
    • @BryanOakley 好的,我想现在我终于做对了,使用 root.after(...)。感谢您的建议!
    • 是的,看起来好多了。如果您在循环中删除对self.canvas.update() 的调用,您可能会获得稍好的性能。这是不必要的,因为一旦函数返回,更新就会自动发生。此外,您可以使用move 方法移动项目,而不是重新配置它的完整坐标。我不知道是否存在性能差异,尽管在紧密循环中少一点代码通常会更快。我不知道它是否明显更快。
    • @LilKasian 当然,只需在bubbles 方法中添加一个for 循环。我已经编辑了我的代码,所以它添加了从 1 到 20 的所有数字。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-27
    • 2016-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多