### 項目分析
- 屏保可以自己啟動,也可以手動啟動
- 一旦敲擊鍵盤或者移動鼠標后,或者其他的引發時間,則停止
- 如果屏保是一幅畫的話,則沒有畫框
- 圖像的動作是隨機的,具有隨機性,可能包括顏色,大小,運動方向,變形等
- 整個世界的構成是:
- ScreenSaver:
- 需要一個canvas,大小與屏幕一致,沒有邊框
- Ball
- 顏色,大小,多少, 運動方向,變形等隨機
- 球能動,可以被調用
----------------------------------------------------
import random
import tkinter
#pythoncom.CoInitialize()
#pythoncom.CoInitialize()
# 定義關於球的類
class RandomBall():
# 自動初始化畫布和屏幕尺寸
def __init__(self, canvas, scrnwidth, scrnheight):
class RandomBall():
# 自動初始化畫布和屏幕尺寸
def __init__(self, canvas, scrnwidth, scrnheight):
self.canvas = canvas
# 定義球的初始位置(x,y),此坐標為球的圓心,位置隨機生成
self.xpos = random.randint(60, int(scrnwidth) - 60)
self.ypos = random.randint(60, int(scrnheight) - 60)
# 定義球在x、y方向上的移動速度,速度隨機給定
self.xvelocity = random.randint(6, 12)
self.yvelocity = random.randint(6, 12)
# 將屏幕尺寸的形參賦給函數內部
self.scrnwidth = scrnwidth
self.scrnheight = scrnheight
# 定義球的半徑,半徑大小隨機給定
self.radius = random.randint(40, 70)
#定義球的顏色
c = lambda:random.randint(0, 255)
self.color = '#%02x%02x%02x' % (c(), c(), c())
# 創建球的函數
def creat_ball(self):
# 通過圓心,獲取一矩形左上角和右下角的坐標
x1 = self.xpos - self.radius
y1 = self.ypos - self.radius
x2 = self.xpos + self.radius
y2 = self.ypos + self.radius
# tkinter沒有創建圓的函數,通過創建橢圓的方式來生成圓
self.item = self.canvas.create_oval(x1, y1, x2, y2, fill=self.color,outline=self.color)
# 定義球的初始位置(x,y),此坐標為球的圓心,位置隨機生成
self.xpos = random.randint(60, int(scrnwidth) - 60)
self.ypos = random.randint(60, int(scrnheight) - 60)
# 定義球在x、y方向上的移動速度,速度隨機給定
self.xvelocity = random.randint(6, 12)
self.yvelocity = random.randint(6, 12)
# 將屏幕尺寸的形參賦給函數內部
self.scrnwidth = scrnwidth
self.scrnheight = scrnheight
# 定義球的半徑,半徑大小隨機給定
self.radius = random.randint(40, 70)
#定義球的顏色
c = lambda:random.randint(0, 255)
self.color = '#%02x%02x%02x' % (c(), c(), c())
# 創建球的函數
def creat_ball(self):
# 通過圓心,獲取一矩形左上角和右下角的坐標
x1 = self.xpos - self.radius
y1 = self.ypos - self.radius
x2 = self.xpos + self.radius
y2 = self.ypos + self.radius
# tkinter沒有創建圓的函數,通過創建橢圓的方式來生成圓
self.item = self.canvas.create_oval(x1, y1, x2, y2, fill=self.color,outline=self.color)
# 創建球移動的函數
def move_ball(self):
# 球的(x,y)坐標根據速度變化不斷更新
self.xpos += self.xvelocity
self.ypos += self.yvelocity
# 當球撞到屏幕邊界后,反彈的算法判斷
if self.xpos + self.radius >= self.scrnwidth:
self.xvelocity = -self.xvelocity
def move_ball(self):
# 球的(x,y)坐標根據速度變化不斷更新
self.xpos += self.xvelocity
self.ypos += self.yvelocity
# 當球撞到屏幕邊界后,反彈的算法判斷
if self.xpos + self.radius >= self.scrnwidth:
self.xvelocity = -self.xvelocity
if self.xpos - self.radius <= 0:
self.xvelocity = -self.xvelocity
self.xvelocity = -self.xvelocity
if self.ypos + self.radius >= self.scrnheight:
self.yvelocity = -self.yvelocity
self.yvelocity = -self.yvelocity
if self.ypos - self.radius <= 0:
self.yvelocity = -self.yvelocity
# 在畫布上移動圖畫
self.canvas.move(self.item, self.xvelocity, self.yvelocity)
self.yvelocity = -self.yvelocity
# 在畫布上移動圖畫
self.canvas.move(self.item, self.xvelocity, self.yvelocity)
# 定義屏保的類
class ScreenSaver():
class ScreenSaver():
def __init__(self):
self.balls = []
# 每次啟動程序,球的數量隨機
self.num_balls = random.randint(6, 20)
# 生成root主窗口
self.root = tkinter.Tk()
#獲取屏幕尺寸,作為主窗口尺寸
self.width = self.root.winfo_screenwidth()
self.height = self.root.winfo_screenheight()
# 取消邊框
self.root.overrideredirect(1)
# 調整背景透明度
self.root.attributes('-alpha', 1)
# 點擊鼠標、移動鼠標、敲擊鍵盤時退出程序
self.root.bind('<Motion>', self.myquit)
self.root.bind('<Any-Button>',self.myquit)
self.root.bind('<Key>', self.myquit)
# 創建畫布,包括畫布的歸屬、尺寸和背景顏色
self.canvas = tkinter.Canvas(self.root,width=self.width,height=self.height,bg = "black")
self.canvas.pack()
# 每次啟動程序,球的數量隨機
self.num_balls = random.randint(6, 20)
# 生成root主窗口
self.root = tkinter.Tk()
#獲取屏幕尺寸,作為主窗口尺寸
self.width = self.root.winfo_screenwidth()
self.height = self.root.winfo_screenheight()
# 取消邊框
self.root.overrideredirect(1)
# 調整背景透明度
self.root.attributes('-alpha', 1)
# 點擊鼠標、移動鼠標、敲擊鍵盤時退出程序
self.root.bind('<Motion>', self.myquit)
self.root.bind('<Any-Button>',self.myquit)
self.root.bind('<Key>', self.myquit)
# 創建畫布,包括畫布的歸屬、尺寸和背景顏色
self.canvas = tkinter.Canvas(self.root,width=self.width,height=self.height,bg = "black")
self.canvas.pack()
# 根據num_balls隨機生成的數值,在畫布上生成球
for i in range(self.num_balls):
# 調用RandomBall函數,自動初始化出不同大小、位置和顏色的球
ball = RandomBall(self.canvas,scrnwidth=self.width, scrnheight=self.height)
# 調用生成球的函數
ball.creat_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(50, self.run_screen_saver)
# 定義一個停止運行的函數
def myquit(self, event):
self.root.destroy()
# 調用函數
for i in range(self.num_balls):
# 調用RandomBall函數,自動初始化出不同大小、位置和顏色的球
ball = RandomBall(self.canvas,scrnwidth=self.width, scrnheight=self.height)
# 調用生成球的函數
ball.creat_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(50, self.run_screen_saver)
# 定義一個停止運行的函數
def myquit(self, event):
self.root.destroy()
# 調用函數
if __name__ == '__main__':
ScreenSaver()
ScreenSaver()
# 球在邊框上蹦躂主要是出生點太靠線球就不會反彈了
# 解決的方法是將出生點設置的高點 設置以下位置
# 定義球的初始位置(x,y),此坐標為球的圓心,位置隨機生成
#self.xpos = random.randint(60, int(scrnwidth) - 60)
#self.ypos = random.randint(60, int(scrnheight) - 60)
