Python升級之路( Lv23 ) GUI圖形界面編程
今天我們將深入學(xué)習圖形界面編程tkinter, 學(xué)習GUI程序的編寫。
GUI程序編寫實踐
今日冒險片段上:
通過背部之后, 他們現(xiàn)在來到的是位于天帷巨獸前段脊椎部位的第一脊椎. 這里坐落著一個螺旋形遠古神殿. 這座神殿歷來都是GBK教的圣殿. 在教徒?jīng)]有被控制之前, 歷代教主都是在此居住, 并主持各種祭祀活動. 因此, 他們必須奪回此神殿.
1. 記事本軟件開發(fā)
結(jié)合所學(xué) GUI 知識,開發(fā)一款模仿 windows 記事本的軟件。包含了基本的功能:
- 新建文本文件
- 保存文件
- 修改文件內(nèi)容
- 退出
- 各種快捷鍵處理
- 修改文本區(qū)域背景色
實操代碼:
"""
結(jié)合所學(xué) GUI 知識,開發(fā)一款模仿 windows 記事本的軟件。包含了基本的功能:
1. 新建文本文件
2. 保存文件
3. 修改文件內(nèi)容
4. 退出
5. 各種快捷鍵處理
6. 修改文本區(qū)域背景色
"""
from tkinter import Frame, Tk, Menu, Text, INSERT, END
from tkinter.filedialog import *
from tkinter.colorchooser import *
class Application(Frame):
def __init__(self, master=None):
super(Application, self).__init__(master)
self.master = master
self.textPad = None # 文本框?qū)ο? self.filename = None # 打開文件的名字
self.contextMenu = None # 上下文菜單對象
self.pack()
self.createWidget()
def createWidget(self):
"""在組件中創(chuàng)建主菜單"""
menubar = Menu(root)
"""創(chuàng)建子菜單"""
menuFile = Menu(menubar)
menuEdit = Menu(menubar)
menuHelp = Menu(menubar)
"""將子菜單放入主菜單欄"""
menubar.add_cascade(label="文件(F)", menu=menuFile)
menubar.add_cascade(label="編輯(E)", menu=menuEdit)
menubar.add_cascade(label="幫助(H)", menu=menuHelp)
"""添加菜單項"""
menuFile.add_command(label="新建", accelerator="ctrl+n", command=self.newfile)
menuFile.add_command(label="打開", accelerator="ctrl+o", command=self.openfile)
menuFile.add_command(label="保存", accelerator="ctrl+s", command=self.savefile)
menuFile.add_separator() # 添加分割線
menuFile.add_command(label="退出", accelerator="ctrl+q", command=self.exit)
# 將主菜單欄加到根窗口
root["menu"] = menubar
# 添加快捷鍵事件處理
root.bind("<Control-n>", lambda event: self.newfile())
root.bind("<Control-o>", lambda event: self.openfile())
root.bind("<Control-s>", lambda event: self.savefile())
root.bind("<Control-q>", lambda event: self.exit())
# 文本編輯區(qū)
self.textpad = Text(root, width=50, height=30)
self.textpad.pack()
# 創(chuàng)建上下菜單
self.contextMenu = Menu(root)
self.contextMenu.add_command(label="背景顏色", command=self.openAskColor)
# 為右鍵綁定事件
root.bind("<Button-3>",self.createContextMenu)
def newfile(self):
self.textpad.delete('1.0','end') # 把 Text 控件中的內(nèi)容清空
self.filename = asksaveasfilename(title='另存為', initialfile='未命名.txt', filetypes=[("文本文檔", "*.txt")], defaultextension='.txt')
print(self.filename)
self.savefile()
def openfile(self):
self.textpad.delete('1.0','end') # 先把 Text 控件中的內(nèi)容清空
with askopenfile(title="打開文件") as f:
self.textpad.insert(INSERT, f.read())
self.filename = f.name
print(f.name)
def savefile(self):
with open(self.filename, "w") as f:
c = self.textpad.get(1.0, END)
f.write(c)
def exit(self):
root.quit()
def openAskColor(self):
s1 = askcolor(color="red", title="選擇背景色")
self.textpad.config(bg=s1[1])
def createContextMenu(self, event): # 菜單在鼠標右鍵單擊的坐標處顯示
self.contextMenu.post(event.x_root, event.y_root)
if __name__ == '__main__':
root = Tk()
root.geometry("450x300+200+300")
root.title("最初的記事本")
app = Application(root)
root.mainloop()
將 python 程序打包成 exe 文件:
- 安裝 pyinstaller 模塊 在 pycharm 中操作:file-->setting-->Project:xxx -->Project interpretor,再點擊+ (加號)在新彈窗中輸入要下載的第三方模塊, 然后點擊該模塊, 最后點擊左下角安裝即可
- 在 pycharm 的 Terminal 終端輸入如下命令:pyinstaller -F xxxx.py需要進入到當前模塊所在目錄下:
注意: pyinstaller相關(guān)參數(shù)如下:
--icon=圖標路徑(pyinstaller
-F --icon=my.ico XXXX.py)
-F 打包成一個 exe 文件
-w 使用窗口,無控制臺
-c 使用控制臺,無窗口
-D 創(chuàng)建一個目錄,里面包含 exe 以及其他一些依賴性文件
在項目的 dist 目錄下可以看到生成了 exe 文件,直接在 windows 系統(tǒng)中使用即可。
2. 畫圖軟件開發(fā)
開發(fā)一款簡單的畫圖軟件, 包含如下功能:
- 畫筆
- 矩形/橢圓繪制
- 清屏
- 橡皮擦
- 直線/帶箭頭的直線
- 修改畫筆顏色、背景顏色
實操代碼:
"""開發(fā)繪圖軟件的菜單"""
from tkinter import Frame, Canvas, Tk, Button, LAST
from tkinter.colorchooser import *
# 窗口的寬度和高度
win_width = 900
win_height = 450
class Application(Frame):
def __init__(self, master=None, bgcolor="#000000"):
super(Application, self).__init__(master)
self.master = master
self.bgcolor = bgcolor
self.x = 0
self.y = 0
self.fgcolor = "#ff0000"
self.lastDraw = 0
self.startDrawFlag = False
self.pack()
self.createWidget()
def createWidget(self):
# 創(chuàng)建繪圖區(qū)
self.drawpad = Canvas(root, width=win_width, height=win_height * 0.9, bg=self.bgcolor)
self.drawpad.pack()
# 創(chuàng)建按鈕
btn_start = Button(root, text="開始", name="start")
btn_start.pack(side="left", padx="10")
btn_pen = Button(root, text="畫筆", name="pen")
btn_pen.pack(side="left", padx="10")
btn_rect = Button(root, text="矩形", name="rect")
btn_rect.pack(side="left", padx="10")
btn_clear = Button(root, text="清屏", name="clear")
btn_clear.pack(side="left", padx="10")
btn_erasor = Button(root, text="橡皮擦", name="erasor")
btn_erasor.pack(side="left", padx="10")
btn_line = Button(root, text="直線", name="line")
btn_line.pack(side="left", padx="10")
btn_lineArrow = Button(root, text="箭頭直線", name="lineArrow")
btn_lineArrow.pack(side="left", padx="10")
btn_color = Button(root, text="顏色", name="color")
btn_color.pack(side="left", padx="10")
# 事件處理
btn_pen.bind_class("Button", "<1>", self.eventManager)
self.drawpad.bind("<ButtonRelease-1>", self.stopDraw)
# 增加顏色切換的快捷鍵
root.bind("<KeyPress-r>", self.kuaijiejian)
root.bind("<KeyPress-g>", self.kuaijiejian)
root.bind("<KeyPress-y>", self.kuaijiejian)
def eventManager(self, event):
name = event.widget.winfo_name()
# print(name)
if name == "line":
self.drawpad.bind("<B1-Motion>", self.myline)
elif name == "lineArrow":
self.drawpad.bind("<B1-Motion>", self.mylineArrow)
elif name == "rect":
self.drawpad.bind("<B1-Motion>", self.myRect)
elif name == "pen":
self.drawpad.bind("<B1-Motion>", self.myPen)
elif name == "erasor":
self.drawpad.bind("<B1-Motion>", self.myErasor)
elif name == "clear":
self.drawpad.delete("all")
elif name == "color":
c = askcolor(color=self.fgcolor, title="選擇畫筆顏色")
# [(255,0,0),"#ff0000"]
self.fgcolor = c[1]
def stopDraw(self, event):
self.startDrawFlag = False
self.lastDraw = 0
def startDraw(self, event):
self.drawpad.delete(self.lastDraw)
if not self.startDrawFlag:
self.startDrawFlag = True
self.x = event.x
self.y = event.y
def myline(self, event):
self.startDraw(event)
self.lastDraw = self.drawpad.create_line(self.x, self.y, event.x, event.y, fill=self.fgcolor)
def mylineArrow(self, event):
self.startDraw(event)
self.lastDraw = self.drawpad.create_line(self.x, self.y, event.x, event.y, arrow=LAST, fill=self.fgcolor)
def myRect(self, event):
self.startDraw(event)
self.lastDraw = self.drawpad.create_rectangle(self.x, self.y, event.x, event.y, outline=self.fgcolor)
def myPen(self, event):
self.startDraw(event)
self.drawpad.create_line(self.x, self.y, event.x, event.y, fill=self.fgcolor)
self.x = event.x
self.y = event.y
def myErasor(self, event):
self.startDraw(event)
self.drawpad.create_rectangle(event.x - 4, event.y - 4, event.x + 4, event.y + 4, fill=self.bgcolor)
self.x = event.x
self.y = event.y
def kuaijiejian(self, event):
if event.char == "r":
self.fgcolor = "#ff0000"
elif event.char == "g":
self.fgcolor = "#00ff00"
elif event.char == "y":
self.fgcolor = "#ffff00"
if __name__ == "__main__":
root = Tk()
root.geometry(str(win_width) + "x" + str(win_height) + "+200+300")
root.title("你的畫圖軟件")
app = Application(root)
root.mainloop()
將 python 程序打包成 exe 文件:
打包步驟同上面筆記本打包步驟一致, 但需注意如果使用 pyinstaller -F paint_release.py 進行打包, 打包后的程序在運行后會啟動一個命令行界面. 因此我們可以在打包時添加 -w, 即 pyinstaller -F -w paint_release.py通過這種命令打包后, 運行程序時便不會同時打包命令行/控制臺
今日冒險片段下:
進入第一脊椎區(qū)域, 這篇區(qū)域的怪物明顯多了很多. 了不起以及伙伴們也感受到了前方的兇險. 至此, gbk教的強者們也不藏著掖著了, 合力召喚出了精靈王伊莎貝拉的虛影. 這是一種通過吸收召喚者魔力的來將遠在異空間的強者精神體召喚出來的技能, 精神體的強弱取決于被召喚者的人數(shù)以及魔力水平. 但唯一遺憾的是, 召喚的人必須是gbk教的人. 但僅僅是這樣, 這個精靈王的投影便展現(xiàn)出極其強大的力量. 光暗冰火四種屬性手到擒來, 而且還有壓制領(lǐng)主能力的效果. 就這樣, 了不起幾乎沒費多大力氣, 就消滅了吞噬信徒們的黑章魚, 等級也順利升至lv24, 在此期間了不起順勢回復(fù)體力, 為后面即將到來的惡戰(zhàn)做準備.