您好,登錄后才能下訂單哦!
這篇“怎么使用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()
以上就是關于“怎么使用Python+Tkinter實現簡單的畫圖軟件”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。