最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python+Tkinter實(shí)現(xiàn)簡(jiǎn)單的畫圖軟件

 更新時(shí)間:2023年04月21日 09:22:38   作者:街 三 仔  
這篇文章主要為大家詳細(xì)介紹了如何利用Python和Tkinter實(shí)現(xiàn)編寫一個(gè)簡(jiǎn)單的畫圖軟件,可以實(shí)現(xiàn)畫圖、保存、撤銷等功能,感興趣的可以了解一下

一起畫圖吧

為什么突然想搞這個(gè)畫圖軟件呢

不瞞各位,是因?yàn)樽罱拥搅艘粋€(gè)很小很小很小小得不能再小的小項(xiàng)目

就是基于Tkinter,做一個(gè)簡(jiǎn)易的畫圖軟件,要求不高,能畫就行,能保存就行,能撤回就行,能導(dǎo)入就行!

于是,遇到項(xiàng)目就精神抖擻的俺,三下五除二的就夸夸夸的寫,終于!花了將近兩個(gè)小時(shí)多的時(shí)間,寫出來(lái)了一個(gè)還用得過(guò)去得畫圖軟件,雖然這個(gè)畫圖軟件是寫出來(lái)了,但是,俺意猶未盡呀(貪婪!太貪婪了!),于是想搞一個(gè)更加NB一點(diǎn)的畫圖軟件,于是我打開瀏覽器(哦不),打開俺滴大腦,想著提升一下畫圖軟件的功能,于是就寫了以下畫圖軟件

畫圖軟件

基本介紹:構(gòu)造一個(gè)GUI圖形界面,主菜單有導(dǎo)入圖片、保存截圖、清屏、撤銷、工具欄等功能,工具欄中有鉛筆畫圖、畫直線、畫矩形、畫圓形、添加文本、橡皮擦、顏色填充、設(shè)置前景色和設(shè)置背景色等功能。

用到的模塊:Tkinter、PIL

畫不多說(shuō),展示一波

話不多說(shuō),介紹一波

導(dǎo)入??蓪?dǎo)入后綴名為jpg、png、gif的圖片,可在軟件上呈現(xiàn)圖片,可進(jìn)行繪畫。

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

清屏。顧名思義,咱就不多說(shuō)了

撤銷。即返回上一步,但是里面有一個(gè)小bug,具體是啥,各位猜猜

工具欄。工具欄里有啥呢?進(jìn)來(lái)看看就知道咯

實(shí)現(xiàn)代碼

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 = []    # 保存所畫圖形的坐標(biāo)
        self.fill_color = None # 保存填充的顏色

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

        self.yesno = 0
        self.function = 1   # 默認(rèn)鉛筆
        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)   # 創(chuàng)建畫布
        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):
        '''主菜單及其關(guān)聯(lián)的函數(shù)'''
        self.menu = tk.Menu(self, bg="red")
        root.config(menu=self.menu)
        self.menu.add_command(label='導(dǎo)入', 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)

        '''子菜單及其關(guān)聯(lián)的函數(shù)'''
        self.menuType = tk.Menu(self.menu, tearoff=0)   # tearoff=0 - 表示無(wú)法將下拉菜單從“工具欄”窗口分離
        self.menu.add_cascade(label='工具欄', menu=self.menuType)  # add_cascade建立菜單類別對(duì)象
        # 在"工具欄"內(nèi)建立菜單列表
        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):     # 導(dǎo)入文件
        filename = tk.filedialog.askopenfilename(title='導(dǎo)入圖片', 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)
        # 清屏后對(duì)數(shù)據(jù)進(jìn)行初始化
        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):  # 點(diǎn)擊鼠標(biāo)左鍵后運(yùn)行此函數(shù)
        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):  # 按下鼠標(biāo)左鍵并移動(dòng)后運(yùn)行此函數(shù)
        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):    # 左鍵鼠標(biāo)釋放后運(yùn)行此函數(shù)
        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))  # 保存圖型的坐標(biāo)
            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))  # 保存圖型的坐標(biāo)
            self.temp.append('oval')

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

    def onRightButtonUp(self, event):   # 在畫布中鼠標(biāo)右鍵按下并松開時(shí),彈出菜單
        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('輸入字號(hào)', 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):  # 設(shè)置前景色
        self.foreColor = tk.colorchooser.askcolor()[1]

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

"""
------------- 截圖 -----------------
"""
def get_real_resolution():
    """獲取真實(shí)的分辨率"""
    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 設(shè)置的屏幕縮放率
# ImageGrab 的參數(shù)是基于顯示分辨率的坐標(biāo),而 tkinter 獲取到的是基于縮放后的分辨率的坐標(biāo)
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)
        # 開始坐標(biāo)文字
        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()
        # 選擇區(qū)域
        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()

        # 無(wú)邊框,沒有最小化最大化關(guān)閉這幾個(gè)按鈕,也無(wú)法拖動(dòng)這個(gè)窗體,程序的窗體在Windows系統(tǒng)任務(wù)欄上也消失
        self.win.overrideredirect(True)
        self.win.attributes('-alpha', 0.25)

        self.is_selecting = False

        # 綁定按 Enter 確認(rèn), 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')    # 設(shè)置軟件大小 - 寬x高
    Draw_designs(root)
    root.mainloop()

項(xiàng)目地址

街三仔畫圖 ~ github

到此這篇關(guān)于Python+Tkinter實(shí)現(xiàn)簡(jiǎn)單的畫圖軟件的文章就介紹到這了,更多相關(guān)Python Tkinter畫圖軟件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python高級(jí)特性 切片 迭代解析

    Python高級(jí)特性 切片 迭代解析

    這篇文章主要介紹了Python高級(jí)特性 切片 迭代解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • Python Scapy隨心所欲研究TCP協(xié)議棧

    Python Scapy隨心所欲研究TCP協(xié)議棧

    今天小編就為大家分享一篇關(guān)于Python Scapy隨心所欲研究TCP協(xié)議棧,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-11-11
  • python中正則的使用指南

    python中正則的使用指南

    正則表達(dá)式(RE)是一種小型的、高度專業(yè)化的編程語(yǔ)言,它內(nèi)嵌在Python中,并通過(guò)re模塊實(shí)現(xiàn)。下面我們就來(lái)詳細(xì)探討下Python中正則表達(dá)式的使用
    2016-12-12
  • Python實(shí)現(xiàn)可設(shè)置持續(xù)運(yùn)行時(shí)間、線程數(shù)及時(shí)間間隔的多線程異步post請(qǐng)求功能

    Python實(shí)現(xiàn)可設(shè)置持續(xù)運(yùn)行時(shí)間、線程數(shù)及時(shí)間間隔的多線程異步post請(qǐng)求功能

    這篇文章主要介紹了Python實(shí)現(xiàn)可設(shè)置持續(xù)運(yùn)行時(shí)間、線程數(shù)及時(shí)間間隔的多線程異步post請(qǐng)求功能,涉及Python網(wǎng)絡(luò)請(qǐng)求的創(chuàng)建、發(fā)送、響應(yīng)、處理等相關(guān)操作技巧,需要的朋友可以參考下
    2018-01-01
  • Python區(qū)塊鏈范圍結(jié)論及Genesis Block的添加教程

    Python區(qū)塊鏈范圍結(jié)論及Genesis Block的添加教程

    這篇文章主要為大家介紹了Python區(qū)塊鏈范圍結(jié)論及Genesis Block的添加,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • 使用PyTorch實(shí)現(xiàn)限制GPU顯存的可使用上限

    使用PyTorch實(shí)現(xiàn)限制GPU顯存的可使用上限

    從?PyTorch?1.4?版本開始,引入了一個(gè)新的功能,可以允許用戶為特定的?GPU?設(shè)備設(shè)置進(jìn)程可使用的顯存上限比例,下面我們就來(lái)看看具體實(shí)現(xiàn)方法吧
    2024-03-03
  • Python實(shí)現(xiàn)對(duì)文件進(jìn)行單詞劃分并去重排序操作示例

    Python實(shí)現(xiàn)對(duì)文件進(jìn)行單詞劃分并去重排序操作示例

    這篇文章主要介紹了Python實(shí)現(xiàn)對(duì)文件進(jìn)行單詞劃分并去重排序操作,涉及Python文件讀取、字符串遍歷、拆分、排序等相關(guān)操作技巧,需要的朋友可以參考下
    2018-07-07
  • python?包實(shí)現(xiàn)?urllib?網(wǎng)絡(luò)請(qǐng)求操作

    python?包實(shí)現(xiàn)?urllib?網(wǎng)絡(luò)請(qǐng)求操作

    這篇文章主要介紹了python包實(shí)現(xiàn)urllib網(wǎng)絡(luò)請(qǐng)求操作,urllib?是?Python?標(biāo)準(zhǔn)庫(kù)中用于網(wǎng)絡(luò)請(qǐng)求的庫(kù),下面urllib的相關(guān)資料介紹,需要的小伙伴可以參考一下
    2022-04-04
  • Python統(tǒng)計(jì)單詞出現(xiàn)的次數(shù)

    Python統(tǒng)計(jì)單詞出現(xiàn)的次數(shù)

    最近經(jīng)理交給我一項(xiàng)任務(wù),統(tǒng)計(jì)一個(gè)文件中每個(gè)單詞出現(xiàn)的次數(shù),列出出現(xiàn)頻率最多的5個(gè)單詞。本文給大家?guī)?lái)了python 統(tǒng)計(jì)單詞次數(shù)的思路解析,需要的朋友參考下吧
    2018-04-04
  • python sorted函數(shù)的小練習(xí)及解答

    python sorted函數(shù)的小練習(xí)及解答

    這篇文章主要介紹了python sorted函數(shù)的小練習(xí)及解答,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09

最新評(píng)論

崇明县| 枣强县| 莎车县| 时尚| 察雅县| 澎湖县| 湖南省| 尚志市| 南投县| 永顺县| 西林县| 青海省| 安丘市| 始兴县| 云龙县| 容城县| 如皋市| 神农架林区| 苏尼特左旗| 沅陵县| 阳江市| 宝兴县| 健康| 襄汾县| 中超| 安国市| 黔东| 株洲市| 抚顺县| 景泰县| 晋中市| 麻江县| 商城县| 深州市| 湘潭市| 仪征市| 蓬安县| 江都市| 天门市| 商洛市| 平阴县|