返回顶部
首页 > 资讯 > 后端开发 > Python >Python+Tkinter实现简单的画图软件
  • 447
分享到

Python+Tkinter实现简单的画图软件

Python 官方文档:入门教程 => 点击学习

摘要

目录一起画图吧画图软件实现代码项目地址一起画图吧 为什么突然想搞这个画图软件呢 不瞒各位,是因为最近接到了一个很小很小很小小得不能再小的小项目 就是基于Tkinter,做一个简易的画

一起画图吧

为什么突然想搞这个画图软件呢

不瞒各位,是因为最近接到了一个很小很小很小小得不能再小的小项目

就是基于Tkinter,做一个简易的画图软件,要求不高,能画就行,能保存就行,能撤回就行,能导入就行!

于是,遇到项目就精神抖擞的俺,三下五除二的就夸夸夸的写,终于!花了将近两个小时多的时间,写出来了一个还用得过去得画图软件,虽然这个画图软件是写出来了,但是,俺意犹未尽呀(贪婪!太贪婪了!),于是想搞一个更加NB一点的画图软件,于是我打开浏览器(哦不),打开俺滴大脑,想着提升一下画图软件的功能,于是就写了以下画图软件

画图软件

基本介绍:构造一个GUI图形界面,主菜单有导入图片、保存截图、清屏、撤销、工具栏等功能,工具栏中有铅笔画图、画直线、画矩形、画圆形、添加文本、橡皮擦、颜色填充、设置前景色和设置背景色等功能。

用到的模块:Tkinter、PIL

画不多说,展示一波

话不多说,介绍一波

导入。可导入后缀名为jpg、png、gif的图片,可在软件上呈现图片,可进行绘画。

保存。任意截取屏幕上的部分,截取好后按下回车键,即可保存,若想退出,则按下esc键

清屏。顾名思义,咱就不多说了

撤销。即返回上一步,但是里面有一个小bug,具体是啥,各位猜猜

工具栏。工具栏里有啥呢?进来看看就知道咯

实现代码

import tkinter as tk
from tkinter import *
import tkinter.simpledialog
import tkinter.colorchooser
import tkinter.filedialog
from PIL import Image, ImageTk, ImageGrab
from tkinter.colorchooser import askcolor
from win32 import win32api, win32gui, win32print
from win32.lib import win32con

from win32.win32api import GetSystemMetrics


class Draw_designs(tk.Frame):
    def __init__(self, master=None):
        tk.Frame.__init__(self, master)
        self.master = master
        self.pack()

        self.temp = []  # 保存图形的类型
        self.li = []    # 保存所画图形的坐标
        self.fill_color = None # 保存填充的颜色

        self.lastDraw = 0
        self.end = [0]
        self.size = "12"    # 字体大小

        self.yesno = 0
        self.function = 1   # 默认铅笔
        self.X = 0
        self.Y = 0

        self.foreColor = '#000000'
        self.backColor = '#FFFFFF'

        self.create_widget()
        self.setMenu()

    def create_widget(self):
        self.image = PhotoImage()
        self.canvas = Canvas(root, bg='white', width=x, height=y)   # 创建画布
        self.canvas.create_image(x, y, image=self.image)

        self.canvas.bind('<Button-1>', self.onLeftButtonDown)
        self.canvas.bind('<B1-Motion>', self.onLeftButtonMove)
        self.canvas.bind('<ButtonRelease-1>', self.onLeftButtonUp)
        self.canvas.bind('<ButtonRelease-3>', self.onRightButtonUp)
        self.canvas.pack(fill=tk.BOTH, expand=tk.YES)

    def setMenu(self):
        '''主菜单及其关联的函数'''
        self.menu = tk.Menu(self, bg="red")
        root.config(menu=self.menu)
        self.menu.add_command(label='导入', command=self.Import)
        self.menu.add_command(label='保存', command=self.SavePicture)
        self.menu.add_command(label='清屏', command=self.Clear)
        self.menu.add_command(label='撤销', command=self.Back)

        '''子菜单及其关联的函数'''
        self.menuType = tk.Menu(self.menu, tearoff=0)   # tearoff=0 - 表示无法将下拉菜单从“工具栏”窗口分离
        self.menu.add_cascade(label='工具栏', menu=self.menuType)  # add_cascade建立菜单类别对象
        # 在"工具栏"内建立菜单列表
        self.menuType.add_command(label='铅笔', command=self.drawCurve)
        self.menuType.add_command(label='直线', command=self.drawLine)
        self.menuType.add_command(label='矩形', command=self.drawRectangle)
        self.menuType.add_command(label='圆形', command=self.drawCircle)
        self.menuType.add_command(label='文本', command=self.drawText)
        self.menuType.add_command(label='橡皮擦', command=self.onErase)
        self.menuType.add_command(label='颜色填充', command=self.fill)
        self.menuType.add_separator()       # 建立分隔线
        self.menuType.add_command(label='选择前景色', command=self.chooseForeColor)
        self.menuType.add_command(label='选择背景色', command=self.chooseBackColor)

    def Import(self):     # 导入文件
        filename = tk.filedialog.askopenfilename(title='导入图片', filetypes=[('image', '*.jpg *.png *.gif')])
        if filename:
            self.image = Image.open(filename)
            self.image = self.image.resize((800, 600), Image.ANTIALIAS)
            self.image = ImageTk.PhotoImage(self.image)
            self.canvas.create_image(400, 300, image=self.image)

    def SavePicture(self):      # 保存画布
        ScreenShot()

    def Clear(self):    # 清屏
        for item in self.canvas.find_all():
            self.canvas.delete(item)
        # 清屏后对数据进行初始化
        self.end = [0]
        self.lastDraw = 0

    def Back(self):     # 撤回
        try:
            for i in range(self.end[-2], self.end[-1] + 1):
                self.canvas.delete(i)
            self.end.pop()
            self.li.pop()

        except:
            self.end = [0]

    def onLeftButtonDown(self, event):  # 点击鼠标左键后运行此函数
        self.yesno = 1
        self.X = event.x
        self.Y = event.y

        if self.function == 7:  # 颜色填充
            for i in range(len(self.li)):
                if (self.X >= self.li[i][0] and self.X <= self.li[i][2]) and (self.Y >= self.li[i][1] and self.Y <= self.li[i][3]):
                    if self.temp[i] == 'rect':
                        rect = self.canvas.create_rectangle(self.li[i][0], self.li[i][1], self.li[i][2], self.li[i][3])
                        self.canvas.itemconfig(rect, fill=self.fill_color)
                        self.end.append(rect)   # 加入撤销列表

                    elif self.temp[i] == 'oval':
                        oval = self.canvas.create_oval(self.li[i][0], self.li[i][1], self.li[i][2], self.li[i][3])
                        self.canvas.itemconfig(oval, fill=self.fill_color)
                        self.end.append(oval)  # 加入撤销列表

                    break

        if self.function == 4:
            self.canvas.create_text(event.x, event.y, font=("等线", int(self.size)), text=self.text, fill=self.foreColor)
            self.function = 1

    def onLeftButtonMove(self, event):  # 按下鼠标左键并移动后运行此函数
        if self.yesno == 0:
            return

        if self.function == 1:    # 铅笔
            self.lastDraw = self.canvas.create_line(self.X, self.Y, event.x, event.y, fill=self.foreColor)
            self.X = event.x
            self.Y = event.y

        elif self.function == 2:  # 画直线
            try:
                self.canvas.delete(self.lastDraw)
            except Exception:
                pass
            self.lastDraw = self.canvas.create_line(self.X, self.Y, event.x, event.y, fill=self.foreColor)

        elif self.function == 3:  # 画矩形
            try:
                self.canvas.delete(self.lastDraw)
            except Exception:
                pass
            self.lastDraw = self.canvas.create_rectangle(self.X, self.Y, event.x, event.y, outline=self.foreColor)

        elif self.function == 5:  # 橡皮擦
            self.lastDraw = self.canvas.create_rectangle(event.x - 10, event.y - 10, event.x + 10, event.y + 10, outline=self.backColor)

        elif self.function == 6:  # 画圆
            try:
                self.canvas.delete(self.lastDraw)
            except Exception:
                pass
            self.lastDraw = self.canvas.create_oval(self.X, self.Y, event.x, event.y, fill=self.backColor, outline=self.foreColor)

    def onLeftButtonUp(self, event):    # 左键鼠标释放后运行此函数
        if self.function == 2:
            self.lastDraw = self.canvas.create_line(self.X, self.Y, event.x, event.y, fill=self.foreColor)

        elif self.function == 3:    # 正方形
            self.lastDraw = self.canvas.create_rectangle(self.X, self.Y, event.x, event.y, outline=self.foreColor)
            self.li.append((self.X, self.Y, event.x, event.y))  # 保存图型的坐标
            self.temp.append('rect')

        elif self.function == 6:    # 圆形
            self.lastDraw = self.canvas.create_oval(self.X, self.Y, event.x, event.y, outline=self.foreColor)
            self.li.append((self.X, self.Y, event.x, event.y))  # 保存图型的坐标
            self.temp.append('oval')

        self.yesno = 0
        if self.function != 7:
            self.end.append(self.lastDraw)

    def onRightButtonUp(self, event):   # 在画布中鼠标右键按下并松开时,弹出菜单
        self.menu.post(event.x_root, event.y_root)

    def drawCurve(self):    # 铅笔
        self.function = 1

    def drawLine(self):     # 直线
        self.function = 2

    def drawRectangle(self):    # 矩形
        self.function = 3

    def drawCircle(self):   # 画圆
        self.function = 6

    def drawText(self):     # 文字
        self.text = tk.simpledialog.askstring(title='输入文本', prompt='')
        if self.text is not None:
            self.size = tk.simpledialog.askinteger('输入字号', prompt='', initialvalue=20)
            if self.size is None:
                self.size = "20"
        self.function = 4

    def onErase(self):  # 橡皮擦
        self.function = 5

    def fill(self):
        c = askcolor(color=self.foreColor, title="选择画笔颜色")
        self.fill_color = c[1]
        self.function = 7

    def chooseForeColor(self):  # 设置前景色
        self.foreColor = tk.colorchooser.askcolor()[1]

    def chooseBackColor(self):  # 设置背景色
        self.backColor = tk.colorchooser.askcolor()[1]

"""
------------- 截图 -----------------
"""
def get_real_resolution():
    """获取真实的分辨率"""
    hDC = win32gui.GetDC(0)
    # 横向分辨率
    w = win32print.GetDeviceCaps(hDC, win32con.DESKTOPHORZRES)
    # 纵向分辨率
    h = win32print.GetDeviceCaps(hDC, win32con.DESKTOPVERTRES)
    return w, h


def get_screen_size():
    """获取缩放后的分辨率"""
    w = GetSystemMetrics(0)
    h = GetSystemMetrics(1)
    return w, h


real_resolution = get_real_resolution()
screen_size = get_screen_size()

# windows 设置的屏幕缩放率
# ImageGrab 的参数是基于显示分辨率的坐标,而 tkinter 获取到的是基于缩放后的分辨率的坐标
screen_scale_rate = round(real_resolution[0] / screen_size[0], 2)


class Box:

    def __init__(self):
        self.start_x = None
        self.start_y = None
        self.end_x = None
        self.end_y = None

    def isNone(self):
        return self.start_x is None or self.end_x is None

    def setStart(self, x, y):
        self.start_x = x
        self.start_y = y

    def setEnd(self, x, y):
        self.end_x = x
        self.end_y = y

    def box(self):
        lt_x = min(self.start_x, self.end_x)
        lt_y = min(self.start_y, self.end_y)
        rb_x = max(self.start_x, self.end_x)
        rb_y = max(self.start_y, self.end_y)
        return lt_x, lt_y, rb_x, rb_y

    def center(self):
        center_x = (self.start_x + self.end_x) / 2
        center_y = (self.start_y + self.end_y) / 2
        return center_x, center_y


class SelectionArea:

    def __init__(self, canvas: tk.Canvas):
        self.canvas = canvas
        self.area_box = Box()

    def empty(self):
        return self.area_box.isNone()

    def setStartPoint(self, x, y):
        self.canvas.delete('area', 'lt_txt', 'rb_txt')
        self.area_box.setStart(x, y)
        # 开始坐标文字
        self.canvas.create_text(
            x, y - 10, text=f'({x}, {y})', fill='red', tag='lt_txt')

    def updateEndPoint(self, x, y):
        self.area_box.setEnd(x, y)
        self.canvas.delete('area', 'rb_txt')
        box_area = self.area_box.box()
        # 选择区域
        self.canvas.create_rectangle(
            *box_area, fill='black', outline='red', width=2, tags="area")
        self.canvas.create_text(
            x, y + 10, text=f'({x}, {y})', fill='red', tag='rb_txt')


class ScreenShot():

    def __init__(self, scaling_factor=2):
        self.win = tk.Tk()
        # self.win.tk.call('tk', 'scaling', scaling_factor)
        self.width = self.win.winfo_screenwidth()
        self.height = self.win.winfo_screenheight()

        # 无边框,没有最小化最大化关闭这几个按钮,也无法拖动这个窗体,程序的窗体在Windows系统任务栏上也消失
        self.win.overrideredirect(True)
        self.win.attributes('-alpha', 0.25)

        self.is_selecting = False

        # 绑定按 Enter 确认, Esc 退出
        self.win.bind('<KeyPress-Escape>', self.exit)
        self.win.bind('<KeyPress-Return>', self.confirmScreenShot)
        self.win.bind('<Button-1>', self.selectStart)
        self.win.bind('<ButtonRelease-1>', self.selectDone)
        self.win.bind('<Motion>', self.changeSelectionArea)

        self.canvas = tk.Canvas(self.win, width=self.width,
                                height=self.height)
        self.canvas.pack()
        self.area = SelectionArea(self.canvas)
        self.win.mainloop()

    def exit(self, event):
        self.win.destroy()

    def clear(self):
        self.canvas.delete('area', 'lt_txt', 'rb_txt')
        self.win.attributes('-alpha', 0)

    def captureImage(self):
        if self.area.empty():
            return None
        else:
            filename = tk.filedialog.asksaveasfilename(filetypes=[('.jpg', 'JPG')],
                                                       initialdir='C:\\Users\\lin042\\Desktop\\')
            box_area = [x * screen_scale_rate for x in self.area.area_box.box()]
            self.clear()
            img = ImageGrab.grab(box_area).save(filename)
            return img

    def confirmScreenShot(self, event):
        img = self.captureImage()
        if img is not None:
            img.show()
        self.win.destroy()

    def selectStart(self, event):
        self.is_selecting = True
        self.area.setStartPoint(event.x, event.y)
        # print('Select', event)

    def changeSelectionArea(self, event):
        if self.is_selecting:
            self.area.updateEndPoint(event.x, event.y)
            # print(event)

    def selectDone(self, event):
        self.is_selecting = False

if __name__ == '__main__':
    x = 1200    # 宽
    y = 600     # 高
    root = tk.Tk()
    root.title('街三仔画图')   # 软件名
    root.geometry('1200x600')    # 设置软件大小 - 宽x高
    Draw_designs(root)
    root.mainloop()

项目地址

街三仔画图 ~ GitHub

到此这篇关于python+Tkinter实现简单的画图软件的文章就介绍到这了,更多相关Python Tkinter画图软件内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Python+Tkinter实现简单的画图软件

本文链接: https://lsjlt.com/news/210658.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Python+Tkinter实现简单的画图软件
    目录一起画图吧画图软件实现代码项目地址一起画图吧 为什么突然想搞这个画图软件呢 不瞒各位,是因为最近接到了一个很小很小很小小得不能再小的小项目 就是基于Tkinter,做一个简易的画...
    99+
    2023-05-17
    Python Tkinter实现画图软件 Python Tkinter画图 Python 画图 Python Tkinter
  • 简单的python画图小实例
    import turtle as t t.goto(100,0) for i in range(100): t.left(80) t.fd(100) t.left(135) t....
    99+
    2023-01-31
    画图 实例 简单
  • python的tkinter如何实现简单登录
    这篇文章主要介绍“python的tkinter如何实现简单登录”,在日常操作中,相信很多人在python的tkinter如何实现简单登录问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”python的tkinte...
    99+
    2023-06-22
  • Android简单实现画图功能
    如何在图片上画画呢?这里写了一个demo,供大家参考 一、先看一眼工程结构 工程结构: 二、自定义view 这个自定义view实现了保留轨迹的功能,代码如下 packag...
    99+
    2022-06-06
    Android
  • Python简单实现图片转字符画的实例项目
    1. 原理 利用 PIL 库来获取图片并修改大小, 利用灰度值转换公式把每一个像素的 RGB 值转为灰度值 gray = int(0.2126*r+0.7152*g+0.0722...
    99+
    2024-04-02
  • jQuery插件实现简单动画
    本篇内容主要讲解“jQuery插件实现简单动画”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“jQuery插件实现简单动画”吧!jQuery 提供了一系列的动画方...
    99+
    2024-04-02
  • 深入了解python的tkinter实现简单登录
    目录通过python的tkinter实现简单的注册登录代码截图登录页面注册页面个人主页修改个人信息失败修改个人信息成功重新登录twb总结通过python的tkinter实现简单的注册...
    99+
    2024-04-02
  • Java实现简单画画画板
    用Java实现简单的画画画板,供大家参考,具体内容如下 一、代码 先直接上代码吧,备注大部分都在代码中。 import java.awt.*; import javax.swing....
    99+
    2024-04-02
  • Python+Tkinter简单实现注册登录功能
    本文实例为大家分享了Python+Tkinter简单实现注册登录功能的具体代码,供大家参考,具体内容如下 项目结构: 源代码: # -*- coding: utf-8 -*...
    99+
    2024-04-02
  • Python+tkinter实现音乐下载软件的制作
    目录前言效果展示代码部分前言 平常我们下载的歌曲,都是各种妖魔鬼怪的格式横行,想下载下来用一下都不行,还只能在它的播放器内听,这谁受得了~ 学Python是用来干嘛的? 当然是解决...
    99+
    2024-04-02
  • Python中的图形绘制简单动画实操
    目录前言:1、画螺旋曲线代码2、输出​​3​、代码的部分解释前言:       Matplotlib 是一个非常广泛的库,它也支持图形动画。 动画工具以...
    99+
    2024-04-02
  • 基于python tkinter的简单计
    import tkinter #定义计算器类 class Calc: #初始化魔术方法 def __init__(self): #初始化共用属性 #定义一个用于存放被计算字符串的列表 self.operationLi...
    99+
    2023-01-31
    简单 python tkinter
  • 软件产品license的简单实现java
    目录 软件License简介License控制内容实现方案代码示例讲解注意事项源码 软件License简介 我们在使用一些需要购买版权的软件产品时,或者我们做的商业软件需要进行售卖,为了收取费用,一般需要一个软件使用许可证,然后...
    99+
    2023-08-16
    java spring boot
  • Python+tkinter实现制作文章搜索软件
    目录前言环境使用模块使用最终效果界面实现代码导入模块创建窗口标题图片搜索框内容显示界面内容效果代码前言 无聊的时候做了一个搜索文章的软件,有没有更加的方便快捷不知道,好玩就行了 环境...
    99+
    2024-04-02
  • python 画图--简单开始及折线图
           本博客转载自:http://blog.csdn.net/jenyzhang/article/details/52046372        相关参考资料:        matplotlib官方文档:http://ma...
    99+
    2023-01-31
    画图 简单 折线图
  • python tkinter制作用户登录界面的简单实现
    本文只是几年前学习的tkinter的时候写的测试程序,十分之简陋,只是学习用,没什么其他用处。 学习一下莫烦Python的tkinter教程,根据教程制作了用户登录注册页。基本功能为...
    99+
    2024-04-02
  • 用python进行简单的画图操作
    我用python的matplotlib模块进行简单的画图操作,作为入门参考,下面直接上代码:#coding:utf-8 import numpy as np import matplotlib.pyplot as plt x=np.lins...
    99+
    2023-01-31
    画图 操作 简单
  • python入门之tkinter实现简
    这次练习的题目是实现一个简单的RSS功能,需要了解的知识点: tkinter,在上一篇《简单的记事本》中已经了解了一些tkinter的用法,在这里延续了上一篇,加深一下印象。 urllib,HTMLPaser库的使用,注意python3...
    99+
    2023-01-31
    入门 python tkinter
  • python tkinter模块的简单使用
    目录1.任务要求 2.简单设计 3.模块实现4.总结由于一些小原因,被迫开始了tkinter一次实战演练。在此做一些记录,总结以及给自己留一些轮子哈哈哈哈哈哈 tkinter 是 P...
    99+
    2024-04-02
  • python Tkinter的简单入门教程
    目录设计代码逐步解释我们将编写一个英尺和米的转换程序,通过这个程序,我们将会了解一个真正的实用程序该怎么设计和编写,我们也将会了解到 Tk 程序内部的基本样子。不必完全掌握里面的所有...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作