吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1876|回复: 1
收起左侧

[Python 转载] 一段熟悉tkinter.Canvas控件的代码实现一个画图功能小软件

[复制链接]
luxingyu329 发表于 2022-4-20 19:05
重新熟悉了一下python代码,发现这东西几天不写就会忘的一干二净,今天无事,写了个窗体控件的代码,顺便回忆了一下事件处理,供像我一样的初学者一个参考,大佬请飘过

[Python] 纯文本查看 复制代码
from tkinter import *
from tkinter.colorchooser import *

# 窗口的全局变量 宽度与高度
win_width = 660
win_height = 380


class Application(Frame):
    """实现一个画图的小软件"""

    def __init__(self, master=None, bg_color='gold', fg_color='DarkOrange'):  # Gold 金 色   DarkOrange 深橙色
        super().__init__(master)
        self.master = master
        self.bg_color = bg_color      # 定义一个背景颜色的对象属性
        self.fg_color = fg_color      # 定义一个前景色
        self.x = self.y = 0           # 起始位置的 x 与 y 初始值
        self.last_draw = 0            # 表示最后绘制的图形的ID
        self.start_draw_flag = False  # 标记最开始的画的位置变量
        self.pack()

        # 下面定义按钮的一些参数        
        self.bin_text = {'start': '开始', 'pen': '画笔', 'rect': '画矩形', 'clear': '清屏', 'eraser': '橡皮擦',
                         'line': '直线', 'line_arrow': '直线(箭头)', 'color': '画笔颜色', 'bg_color': '背景颜色', 'quit': '退出'}

        # 下面开始实现控件 设置一个宽度随窗口,高度为root窗口0.9倍的大小的数值,背景色设置为默认传参的 粉色
        self.draw_pad = Canvas(self, width=win_width, height=win_height*0.9, bg=self.bg_color)
        self.draw_pad.pack()

        # 采用循环的方式创建按钮
        for k, v in self.bin_text.items():
            # index = self.bin_text.index(i)
            self.btn = Button(self, text=v, name=k)
            self.btn.pack(side='left', padx=10)

        # 按钮类事件处理
        self.btn.bind_class('Button', '<Button-1>', self.event_massage)
        # 鼠标释放,为了解决 self.start_draw_flag为True后起点一直是一个点的问题
        self.draw_pad.bind('<ButtonRelease-1>', self.stop_draw)
        # 颜色快捷键的设置
        root.bind('<KeyPress-r>', self.kjj)   # 设置红色的快捷键
        root.bind('<KeyPress-g>', self.kjj)   # 设置绿的快捷键
        root.bind('<KeyPress-y>', self.kjj)   # 设置黄色的快捷键

    # 事件管理
    def event_massage(self, event):
        name = event.widget.winfo_name()
        # print(name)
        if name == 'line':
            self.draw_pad.bind('<B1-Motion>', self.my_line)  # B1-Motion 是按住鼠标拖动的事件

        elif name == 'line_arrow':
            self.draw_pad.bind('<B1-Motion>', self.my_line_arrow)  # B1-Motion 是按住鼠标拖动的事件

        elif name == 'rect':
            self.draw_pad.bind('<B1-Motion>', self.my_rect)  # B1-Motion 是按住鼠标拖动的事件

        elif name == 'pen':
            self.draw_pad.bind('<B1-Motion>', self.my_pen)  # B1-Motion 是按住鼠标拖动的事件

        elif name == 'eraser':
            self.draw_pad.bind('<B1-Motion>', self.my_eraser)  # B1-Motion 是按住鼠标拖动的事件

        elif name == 'color':
            cor = askcolor(title='选择画笔颜色', color=self.fg_color)
            self.fg_color = cor[1]

        elif name == 'bg_color':
            cor = askcolor(title='选择背景颜色', color=self.bg_color)
            self.bg_color = cor[1]
            self.draw_pad['bg'] = self.bg_color
            [color=Magenta]event.widget.state = 'Disabled'[/color]

        elif name == 'clear':
            self.draw_pad.delete('all')  # 直接清除全部就 ok 了

        elif name == 'quit':  # 设置程序的退出机制
            root.destroy()

    # 让self.start_draw_flag为初始
    def stop_draw(self, event):
        self.start_draw_flag = False
        self.last_draw = event.x * 0      # 这样解决画新线删除旧线的问题,改变一下 Self.last_draw的值找不到原来的值my_line函数里也就删除不了了

    # 重复代码精简封装一下 一个新的函数方法
    def start_draw(self, event):
        # 每次调用这个函数方法之前都删除掉前面的线,
        # print('要删除的是什么东西?:', self.last_draw)
        self.draw_pad.delete(self.last_draw)

        # 判断起始位置是不是False
        if not self.start_draw_flag:  # 如果是False说明第一次画
            self.start_draw_flag = True
            self.x = event.x  # 一开始的 x
            self.y = event.y  # 一载始的 y

    # 画直线的函数方法
    def my_line(self, event):        
        # 直接调用 start_draw方法
        self.start_draw(event)
        # 开始画一条直线
        self.last_draw = self.draw_pad.create_line(self.x, self.y, event.x, event.y, fill=self.fg_color)

    # 画带箭头的直线的函数方法
    def my_line_arrow(self, event):
        # 直接调用 start_draw方法
        self.start_draw(event)
        # 开始画一条带箭头的直线  区别是只加一个参数就可以了  就是加一个 arrow=LAST
        self.last_draw = self.draw_pad.create_line(self.x, self.y, event.x, event.y, arrow=LAST,  fill=self.fg_color)

    # 画矩形的函数方法
    def my_rect(self, event):
        # 直接调用 start_draw方法
        self.start_draw(event)

        # # 开始画一个矩形,下面代码是全部填充的样式
        # self.last_draw = self.draw_pad.create_rectangle(self.x, self.y, event.x, event.y, fill=self.fg_color)

        # 开始画一个矩形,下面代码是不进行填充的样式  outline 表示的是边框颜色
        self.last_draw = self.draw_pad.create_rectangle(self.x, self.y, event.x, event.y, outline=self.fg_color)

    # 利用画直线 的方法进行画笔功能的实现,就是一小段一小段的直线连起来,但是要去掉self.last_draw,这样就留住了,不删除了
    def my_pen(self, event):
        # 直接调用 start_draw方法
        self.start_draw(event)
        # 开始画一条带箭头的直线  区别是只加一个参数就可以了  就是加一个 arrow=LAST
        self.draw_pad.create_line(self.x, self.y, event.x, event.y, fill=self.fg_color)
        # 重新给self.x 与 self.y进行赋值,这样起点就会随鼠标移动一直变化 了
        self.x = event.x
        self.y = event.y

    # 橡皮擦
    def my_eraser(self, event):
        # 就是画一个背景色的矩形,下面代码是全部填充的样式
        self.last_draw = self.draw_pad.create_rectangle(event.x-4, event.y-4, event.x+4, event.y+4,
                                                        outline=self.bg_color, fill=self.bg_color)

    # 快捷键函数方法
    def kjj(self, event):
        if event.char == 'r':
            self.fg_color = '#ff0000'
        if event.char == 'g':
            self.fg_color = '#00ff00'
        if event.char == 'y':
            self.fg_color = 'yellow'  # #ffff00


if __name__ == '__main__':
    root = Tk()
    root.geometry(f'{win_width}x{win_height}+500+180')
    root.title('画图小工具---> by: luxingyu329')
    # root['bg'] = 'yellow'
    app = Application(master=root)  # 实例化对象
    root.mainloop()

免费评分

参与人数 3吾爱币 +2 热心值 +3 收起 理由
lypxynok + 1 + 1 用心讨论,共获提升!
Kuroisora + 1 + 1 谢谢@Thanks!
MyModHeaven + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

wuyongkui 发表于 2022-4-21 06:32
没看懂啥意思。但还是要谢谢楼主
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 07:57

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表