【提高篇】python使用tkinter实现透明窗体上绘制美丽的飞机(第四篇)

继续写这个专题,欢迎持续关注,相信你一定会有所收获。
今天是在上述三篇的基础上,进一步提高,实现:

python使用tkinter实现透明窗体上绘制美丽的飞机

飞机,即图片,跟小球最大的区别在于:其实2D图形,需要考虑的东东更多,譬如旋转的角度。因此在实现之初,需要研究如何使图片旋转。

文章目录

  • 一、飞机旋转
    • (一)核心代码
    • (二)完整代码
    • (三)运行效果
  • 二、飞机类实现
    • (一)飞机类环境参数初始化
    • (二)飞机类功能参数初始化
    • (三)核心代码部分
    • (四)飞机类运动部分
  • 三、主体功能实现
    • (一)初始化飞机对象
    • (二)飞机类移动函数
    • (三)完整的主体函数
  • 四、初始运行效果
  • 五、优化参数
  • 六、最终运行效果

一、飞机旋转

(一)核心代码

实现飞机自动旋转


def move_plane(canvas,root):
    global angle,canvas_obj,kk,image,tkimage
    # kk =
    tkimage = ImageTk.PhotoImage(image.rotate(-angle))
    # del kk
    # kk.append(tkimage)
    if canvas_obj is not None:
        canvas.delete(canvas_obj)
    canvas_obj = canvas.create_image(250, 250, image=tkimage)
    angle += 1
    angle %= 360
    print(angle)

    canvas.after(10, move_plane, canvas, tk)

(二)完整代码

from PIL import ImageTk,Image
import tkinter as tk

root = tk.Tk()
root.geometry('600x500+300+100')
root.title('有趣的透明窗体-开篇了!!!')
canvas = tk.Canvas(root)
canvas.pack(fill=tk.BOTH, expand=tk.Y)
root.update()
angle = 0
canvas_obj = None
image = Image.open('plane.png')
tkimage = None

def move_plane(canvas,root):
    global angle,canvas_obj,kk,image,tkimage
    # kk =
    tkimage = ImageTk.PhotoImage(image.rotate(-angle))
    # del kk
    # kk.append(tkimage)
    if canvas_obj is not None:
        canvas.delete(canvas_obj)
    canvas_obj = canvas.create_image(250, 250, image=tkimage)
    angle += 1
    angle %= 360
    print(angle)

    canvas.after(10, move_plane, canvas, tk)

move_plane(canvas,root)

root.mainloop()

(三)运行效果

【提高篇】python使用tkinter实现透明窗体上绘制美丽的飞机(第四篇)_第1张图片

二、飞机类实现

(一)飞机类环境参数初始化

    def __init__(self, canvas,root):
        self.canvas = canvas
        self.root = root
        self.image = Image.open('plane.png')

(二)飞机类功能参数初始化

    def create_ball(self):
        # tkinter绘图采用屏幕坐标系,原点在左上角,x从左往右递增,y从上往下递增
        # 随机产生表示当前球的大小,也就是半径长度
        self.radius = randint(2, 10)

        self.scrnwidth = int(self.root.winfo_width())
        self.scrnheight = int(self.root.winfo_height())

        # 在绘图区域内,随机产生当前球的圆心的x坐标和y坐标,用于制定出现的位置
        self.xpos = randint(self.radius, int(self.root.winfo_width())-self.radius)
        self.ypos = randint(self.radius, int(self.root.winfo_height())-self.radius)


        # 在绘图区域内,随机产生当前球的x坐标和y坐标的向量
        # 在数学中,几何向量(也称矢量),指具有大小和方向的量
        # 这里我们可以用来表示球的速度
        self.xvelocity = randint(2, 6)
        self.yvelocity = randint(2, 6)

        self.angle = math.atan2(self.yvelocity,self.xvelocity)
        self.fangle = math.degrees(self.angle)+90
        self.tkimage = ImageTk.PhotoImage(self.image.rotate(-self.fangle))
        self.canvas_obj = canvas.create_image(self.xpos, self.ypos, image=self.tkimage)

        # 通过lambda表达式创建函数对象r,每次调用r()都会产生0~255之间的数字
        r = lambda: randint(0, 255)

        # 三次调用的数字取前两位,用十六进制数方式存储到self.color里,作为球的颜色
        # RRGGBB,前2是红色,中2是绿色,后2是蓝色,最小是0,最大是F

        # 如全黑#000000  全白#FFFFFF  全红#FF0000
        self.color = "#%02x%02x%02x" % (r(), r(), r())

        # canvas.create_oval可以绘制一个圆
        # 但是需要传入圆的左、上、右、下四个坐标
        # 所以我们先产生4个坐标,通过这个四个坐标,绘制圆的大小

        # 左坐标=x坐标-半径
        x1 = self.xpos - self.radius
        # 上坐标=y坐标-半径
        y1 = self.ypos - self.radius
        # 右坐标=x坐标+半径
        x2 = self.xpos + self.radius
        # 下坐标=y坐标+半径
        y2 = self.ypos + self.radius

        # 通过canvas.create_oval()方法绘出整个圆,填充色和轮廓色分别是self.color生成的颜色
        # self.canvas.delete('ball')
        # self.ball = self.canvas.create_oval(x1, y1, x2, y2, fill=self.color, outline=self.color,tag='ball')
        # canvas.addtag_all('t5')
        print(x1,y1,x2,y2,self.color,self.radius,self.angle,self.fangle)

(三)核心代码部分

        self.angle = math.atan2(self.yvelocity,self.xvelocity)
        self.fangle = math.degrees(self.angle)+90
        self.tkimage = ImageTk.PhotoImage(self.image.rotate(-self.fangle))
        self.canvas_obj = canvas.create_image(self.xpos, self.ypos, image=self.tkimage)

实现飞机旋转和图像更新

(四)飞机类运动部分

    def move_ball(self):
        # 进行相应的移动,如果坐标超过屏幕边缘则向相反方向移动
        # 让球的x坐标和y坐标,按照向量的大小进行增加,表示球的运行,向下和向右

        print(self.color,self.radius,self.angle,self.fangle)
        self.scrnwidth = int(self.root.winfo_width())
        self.scrnheight = int(self.root.winfo_height())

        self.xpos += self.xvelocity
        self.ypos += self.yvelocity

        # 如果球的y坐标大于等于屏幕高度和球的半径的差,则调整球的运行y轴方向朝上
        if self.ypos >= self.scrnheight - self.radius:
            self.yvelocity = -self.yvelocity
            self.angle = math.atan2(self.yvelocity, self.xvelocity)
            self.fangle = math.degrees(self.angle) + 90
            self.tkimage = ImageTk.PhotoImage(self.image.rotate(-self.fangle))
            self.canvas_obj = canvas.create_image(self.xpos, self.ypos, image=self.tkimage)

        # 如果球的y坐标小于等于屏幕高度和球的半径的差,则调整球的y轴运行方向朝下
        if self.ypos <= self.radius:
            self.yvelocity = abs(self.yvelocity)
            self.angle = math.atan2(self.yvelocity, self.xvelocity)
            self.fangle = math.degrees(self.angle) + 90
            self.tkimage = ImageTk.PhotoImage(self.image.rotate(-self.fangle))
            self.canvas_obj = canvas.create_image(self.xpos, self.ypos, image=self.tkimage)

        # 如果球的x坐标大于等于屏幕宽度和球的半径差,则调整球的运行x轴方向朝左
        if self.xpos >= self.scrnwidth - self.radius:
            self.xvelocity = -self.xvelocity
            self.angle = math.atan2(self.yvelocity, self.xvelocity)
            self.fangle = math.degrees(self.angle) + 90
            self.tkimage = ImageTk.PhotoImage(self.image.rotate(-self.fangle))
            self.canvas_obj = canvas.create_image(self.xpos, self.ypos, image=self.tkimage)

        # 如果球的x坐标小于等于屏幕宽度和球半径的差,则调整球的运行x轴方向朝右
        if self.xpos <= self.radius:
            self.xvelocity = abs(self.xvelocity)
            self.angle = math.atan2(self.yvelocity, self.xvelocity)
            self.fangle = math.degrees(self.angle) + 90
            self.tkimage = ImageTk.PhotoImage(self.image.rotate(-self.fangle))
            self.canvas_obj = canvas.create_image(self.xpos, self.ypos, image=self.tkimage)

        # 调整canvas对象的move()方法可以让对象动起来,以及对象x轴和y轴的向量大小
        self.canvas.move(self.canvas_obj, self.xvelocity, self.yvelocity)

三、主体功能实现

(一)初始化飞机对象

    balls = []
    num = 10
    for i in range(num):
        ball = Ball(canvas, tk)
        ball.create_ball()
        balls.append(ball)

(二)飞机类移动函数


def move_balls():
    for ball in balls:
        ball.move_ball()
    canvas.after(20, move_balls)

(三)完整的主体函数

if __name__ == '__main__':
    tk = Tk()
    tk.geometry('800x600+300+100')
    tk.title('有趣的透明窗体-开篇了!!!')
    tk.wm_attributes('-transparentcolor', TRANSCOLOUR)
    tk.bind('', on_resize)

    canvas = Canvas(tk)
    canvas.pack(fill=BOTH, expand=Y)
    tk.update()

    balls = []
    num = 10
    for i in range(num):
        ball = Ball(canvas, tk)
        ball.create_ball()
        balls.append(ball)

    move_balls()

    tk.mainloop()

四、初始运行效果

五、优化参数

tk.wm_attributes("-topmost", 1)
tk.overrideredirect(1)
canvas.config(highlightthickness=0)

六、最终运行效果

代码量不大,效果还行。
希望上热搜,粉丝过万,哈哈。
再深入研究可以有更多更有趣的应用。

分享是一种快乐,希望我们一起快乐,我走过的坎、尝试过的bug,希望你们可以不用再尝试。
对代码有兴趣的朋友们,欢迎关注和点赞,后续我会分享这部分的完整代码给各位,希望大家不是拿来主义,能点点赞、关注一下我啊。
欢迎持续关注,比心。

你可能感兴趣的:(tkinter桌面专栏,python,canvas,tkinter,游戏)