python使用tkiner創建一個小球滾動的代碼


#  tkinter - 項目實戰

'''

- 項目分析
    - 屏保可以自己啟動,也可以手動啟動.
    - 一旦敲擊鍵盤或者移動鼠標,或者引發事件,則停止.
    - 如果屏保是一幅畫的話,則沒有畫框.
    - 圖像的動作是隨機的,具有隨機性.(包括顏色,大小,運動方向,變形)

    - 整個世界的構成是
        - ScreenSaver
            - 需要一個canvas. 大小等於屏幕大小,沒有邊框.
        - Ball
            - 包括顏色,大小,運動方向,變形 => 隨機
            - 球能動, 可以被調用.

'''

import tkinter as tk
import random

class RandomBall:
    '''
    定義一個運動球的類
    '''
    def __init__(self,canvas,scrnWidth,scrnHeight):

        '''
        canvas:畫布,所有的內容都應該在畫布上呈現出來.此處通過此變量傳入
        scrnWidth/scrnheigh:屏幕寬高

        '''
        self.canvas = canvas # 這個是自己添加的.添加原因是下方代碼並沒有 self.canvas

        # 球出現的初始位置要隨機.此位置表示圓心
        
        # xpos表示位置的x坐標
        self.xops = random.randint(10,int(scrnWidth)-20)

        # ypos表示位置y的坐標
        self.yops = random.randint(10,int(scrnHeight)-20)

        # 定義球運動的速度 => 模擬運動: 動畫的邏輯就是重繪 =>模擬運動,不斷的擦掉舊事物,重新繪制新事物
        self.xvelocity = random.randint(4,20)
        self.yvelocity = random.randint(4,20)

        # 定義屏幕的寬度和高度
        self.scrnWidth = scrnWidth
        self.scrnHeight = scrnHeight

        # 球的大小隨機.
        # 此處球的大小用半徑表示
        self.radius = random.randint(20,80)


        # 定義顏色
        # RGB表示法:三個數字,每個數字的值是0-255之間,表示RGB
        c = lambda:random.randint(0,255)

        self.color = '#%02x%02x%02x'%(c(),c(),c()) # 這個地方存疑


    def  create_ball(self):#定義一個函數
        
        '''
        用構造函數定義的變量值,在canvas上畫一個球
        '''
        # tkinter沒有畫圓形的函數
        # 只有一個畫橢圓函數,畫橢圓需要定義兩個坐標
        # 在一個長方形內畫橢圓,我們只需要定義長方形左上角和右下角就好 => 如果是一個正方形,那么橢圓就是圓
        # 求兩個坐標的方法是 (圓心 - 半徑)
        x1 = self.xops - self.radius
        y1 = self.yops - self.radius # 橢圓的左上角
        x2 = self.xops + self.radius
        y2 = self.yops + self.radius # 橢圓的右下角

        self.item = self.canvas.create_oval(x1,y1,x2,y2,fill=self.color,outline=self.color) # 繪制橢圓

    def move_ball(self):
        
        # 移動球的時候,控制球的方向
        # 每次移動后,球都有一個新的坐標
        self.xops += self.xvelocity
        self.yops += self.yvelocity

        # 以下判斷是否會撞牆 => 撞牆的算法判斷

        if self.xops +self.radius>=self.scrnWidth: #撞到右邊的牆了
            self.xvelocity*=-1
        elif self.xops+self.radius<=0:
            self.xvelocity*=-1
        
        if self.yops + self.radius >=self.scrnHeight:
            self.yvelocity*=-1
        elif self.yops +self.radius <= 0:
            self.yvelocity *=-1




        # 在畫布上移動動畫
        self.canvas.move(self.item,self.xvelocity,self.yvelocity)


class ScreenSaver:
    '''
    定義屏保的類
    可以被啟動
    '''
    # 如何裝隨機產生的球
    balls = list()

    def __init__(self):
        
        self.num_balls = random.randint(6,20)

        self.root = tk.Tk()
        
        # 取消邊框
        self.root.overrideredirect(1)

        # 任何鼠標移動都要取消
        self.root.bind('<Motion>',self.myquit)

        # 同理,安東任何鍵盤都需要退出屏保

        # 得到 屏幕大小規格
        w,h = self.root.winfo_screenwidth(),self.root.winfo_screenheight()

        self.canvas = tk.Canvas(self.root,width=w,height=h) # 畫布的歸屬,規格

        self.canvas.pack() # 布局


        # 在畫布上畫球
        for i in range(self.num_balls):
            ball = RandomBall(self.canvas,scrnWidth=w,scrnHeight=h)
            ball.create_ball()
            self.balls.append(ball)

        self.run_screen_saver()
        self.root.mainloop() # 啟動消息循環

    def run_screen_saver(self):
        for ball in self.balls:
            ball.move_ball()                
        # 系統函數 /after是200毫秒后啟動一個函數,需要啟動的函數是第二個參數
        self.canvas.after(20, self.run_screen_saver)


    def myquit(self,e):
        # 此處只是利用了事件處理機制
        # 實際上並不關心事件的類型 
        # 作業:
        # 此屏保程序擴展成,一旦捕獲事件,則判斷屏保不退出
        # 顯示一個Button,Button上顯示事件類型,點擊Button后屏保
        # 才退出
        self.root.destroy()
        
if __name__ == "__main__":
    ScreenSaver()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM