python tkinter 屏保
阿新 • • 發佈:2018-12-21
第一次用python寫的小程式,記錄下。
需求:
- 屏保可以自己啟動,也可以手動啟動
- 一旦敲擊鍵盤或者移動滑鼠後,或者其他的引發時間,則停止
- 如果屏保是一幅畫的話,則沒有畫框
- 影象的動作是隨機的,具有隨機性,可能包括顏色,大小,多少, 運動方向,變形等
- 整個世界的構成是:
-
ScreenSaver:
- 需要一個canvas, 大小與螢幕一致,沒有邊框
-
Ball
- 顏色,大小,多少, 運動方向,變形等隨機
- 球能動,可以被呼叫
-
from tkinter import * import random class RandomBall(): # 定義運動的球的類 def __init__(self,canvas,scrnwidth,scrnheight): # canvas: 畫布,所有的內容都應該在畫布上呈現出來,此處通過此變數傳入 # scrnwidth/scrnheigh:螢幕寬高 # 球出現的初始位置要隨機,此處位置表示的球的圓心 # xpos表示位置的x座標 # print(type(canvas)) self.canvas = canvas self.xpos = random.randint(10,int(scrnwidth) - 20) # ypos表示位置的y座標 self.ypos = random.randint(10, int(scrnwidth) - 20) # 定義球運動的速度 # 模擬運動:不斷的擦掉原來畫,然後在一個新的地方再從新繪製 # 此處xvelocity模擬x軸方向運動 self.xvelocity = random.randint(4, 20) # 同理,yvelocity模擬的是y軸方向運動 self.yvelocity = random.randint(4, 20) # 定義螢幕的大小 self.scrnwidth = scrnwidth # 定義螢幕的高度 self.scrnheight = scrnheight # 球的大小隨機 # 此處球的大小用半徑表示 self.radius = random.randint(20, 120) # 定義顏色 # RGB表示法:三個數字,每個數字的值是0-255之間,表示紅綠藍三個顏色的大小 # 在某些系統中,之間用英文單詞表示也可以,比如red, green # 此處用lambda表示式 c = lambda: random.randint(0, 255) self.color = '#%02x%02x%02x' % (c(), c(), c()) def create_ball(self): # 用建構函式定義的變數值,在canvas上畫一個球 # tkinter沒有畫圓形函式 # 只有一個畫橢圓函式,畫橢圓需要定義兩個座標, # 在一個長方形內畫橢圓,我們只需要定義長方形左上角和右下角就好 # 求兩個座標的方法是,已知圓心的座標,則圓心座標減去半徑能求出 # 左上角座標,加上半徑能求出右下角座標 x1 = self.xpos - self.radius y1 = self.ypos - self.radius x2 = self.xpos + self.radius y2 = self.ypos + self.radius # 繼續球y1, x2, y2 # 再有兩個對角座標的前提下,可以進行畫圓 # fill表示填充顏色 # outline是外圍邊框顏色 self.item = self.canvas.create_oval(x1, y1, x2, y2,fill=self.color,outline=self.color) def move_ball(self): # 移動球的時候,需要控制球的方向 # 每次移動後,球都有一個新的座標 self.xpos += self.xvelocity # 同理計算ypos self.ypos += self.yvelocity # 以下判斷是會否撞牆 # 撞了南牆就要回頭 # 注意撞牆的演算法判斷 if self.xpos + self.radius >= self.scrnwidth: self.xvelocity = -self.xvelocity # 裝到了右邊牆 if self.ypos + self.radius >= self.scrnheight: self.yvelocity = -self.yvelocity if self.ypos <=self.radius : self.yvelocity = abs(self.yvelocity ) if self.xpos <= self.radius: self.xvelocity = abs(self.xvelocity) # self.xvelocity *= -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() # 取消邊框 self.root.overrideredirect(1) # 任何滑鼠移動都需要取消 self.root.bind('<Motion>', self.myquit) # 同理,按動任何鍵盤都需要退出屏保 # 得到螢幕大小規格 w, h = self.root.winfo_screenwidth(), self.root.winfo_screenheight() # 建立畫布,包括畫布的歸屬,規格 self.canvas = Canvas(self.root, width=w, height=h) self.canvas.pack() print(self.canvas) # 在畫布上畫球 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(200, self.run_screen_saver) def myquit(self, e): # 此處只是利用了事件處理機制 # 實際上並不關心事件的型別 # 作業: # 此屏保程式擴充套件成,一旦捕獲事件,則判斷屏保不退出 # 顯示一個Button,Button上顯示事件型別,點選Button後屏保 # 才退出 self.root.destroy() if __name__ == "__main__": # 啟動屏保 ScreenSaver()