找回密码
  注册[Register]
查看: 224|回复: 6

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

[复制链接]
发表于 2022-4-21 08:19 | 显示全部楼层 |阅读模式
禁止求评分、诱导评分、互刷评分、互刷悬赏值,违规者封号处理。
禁止发布推广、邀请码、邀请链接、二维码或者有利益相关的任何推广行为。
所有非原创软件请发布在【精品软件区】,发帖必须按照本版块版规格式发帖。

[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()

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心值】和【牛币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
发表于 2022-4-21 08:19 | 显示全部楼层

感谢楼主的分享
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心值】和【牛币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 有用 没用

使用道具 举报

发表于 2022-4-21 08:32 | 显示全部楼层
6666
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心值】和【牛币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 有用 没用

使用道具 举报

发表于 2022-4-21 08:33 | 显示全部楼层
谢谢@Thanks!
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心值】和【牛币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 有用 没用

使用道具 举报

发表于 2022-4-21 08:34 | 显示全部楼层
先收藏了,万一用到呢
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心值】和【牛币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 有用 没用

使用道具 举报

发表于 2022-4-21 08:34 | 显示全部楼层
谢谢大牛
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心值】和【牛币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 有用 没用

使用道具 举报

发表于 2022-4-21 08:50 | 显示全部楼层
感谢楼主分享!大牛有你更精彩!
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心值】和【牛币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 有用 没用

使用道具 举报

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

RSS订阅|手机版|小黑屋|广告投放|大牛论坛

GMT+8, 2024-5-14 22:28 , Processed in 0.038300 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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