python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

2024-06-20 1547阅读

python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

✨✨ 欢迎大家来到景天科技苑✨✨

🎈🎈 养成好习惯,先赞后看哦~🎈🎈

🏆 作者简介:景天科技苑

🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。

🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,linux,shell脚本等实操经验,网站搭建,数据库等分享。

所属的专栏:python图形化GUI编程tkinter精讲

景天的主页:景天科技苑

文章目录

  • 菜单
    • 1.主菜单
      • 1.1【示例】记事本软件的主菜单
      • 2.上下文菜单
        • 2.1【示例】为记事本程序增加上下文菜单
        • 3.【项目】记事本软件开发
        • 4.【项目】画图软件开发

          菜单

          GUI 程序通常都有菜单,方便用户的交互。我们一般将菜单分为两种:

          1. 主菜单

            主菜单通常位于 GUI 程序上方。例如:

            python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          2. 快捷菜单(上下文菜单)

            通过鼠标右键单击某个组件对象而弹出的菜单,一般是与该组件相关的操作。

            python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          1.主菜单

          主菜单一般包含:文件、编辑、帮助等,位于 GUI 窗口的上面。创建主菜单一般有如下 4

          步:

          1. 创建主菜单栏对象
          menubar = tk.Menu(root)
          
          1. 创建菜单,并添加到主菜单栏对象
          file_menu = tk.Menu(menubar)
          menubar.add_cascade(label=”文件”,menu=file_menu)
          
          1. 添加菜单项到 2 步中的菜单
          file_menu.add_command(label=”打开”)
          file_menu.add_command(label=”保存”,accelerator=”^p” command=mySaveFile)
          file_menu.add_separator()
          file_menu.add_command(label=”退出”)
          
          1. 将主菜单栏添加到根窗口
          root[“menu”]=menubar
          

          1.1【示例】记事本软件的主菜单

          #记事本软件,练习主菜单的设计
          from tkinter import *
          from tkinter.filedialog import *
          root = Tk();root.geometry("400x400")
          root.title("记事本")
          #创建主菜单栏
          menubar = Menu(root)
          #创建子菜单
          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)
          filename = ""
          def openfile():
              global filename
              w1.delete('1.0', 'end')         # 先把Text控件中的内容清空
              with askopenfile() as f:
                  content = f.read()
                  w1.insert(INSERT, content)
                  filename = f.name
                  print(f.name)
          def savefile():
              with open(filename, "w") as f:
                  content = w1.get(1.0, END)
                  f.write(content)
          def exit():
              root.quit()
          # 添加菜单项
          #accelerator 快捷键
          menuFile.add_command(label="打开", accelerator="ctrl+o", command=openfile)
          menuFile.add_command(label="保存", command=savefile)
          menuFile.add_separator()  # 添加分割线
          menuFile.add_command(label="退出", command=exit)
          # 将主菜单栏加到根窗口
          root["menu"] = menubar
          w1 = Text(root, width=50, height=30)
          w1.pack()
          root.mainloop()
          

          运行

          python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          点击文件

          python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          2.上下文菜单

          快捷菜单(上下文菜单)是通过鼠标右键单击组件而弹出的菜单,一般是和这个组件相关的

          操作,比如:剪切、复制、粘贴、属性等。创建快捷菜单步骤如下:

          1. 创建菜单
          menubar = tk.Menu(root)
          menubar.add_command(label=”字体”)
          
          1. 绑定鼠标右键单击事件
          def test(event):
            menubar.post(event.x_root,event.y_root) #在鼠标右键单击坐标处显示菜单
            root.bind(“”,test)
          

          2.1【示例】为记事本程序增加上下文菜单

          """开发记事本软件的菜单
          """
          from tkinter import *
          class Application(Frame):
              def __init__(self, master=None):
                  super().__init__(master)        # super()代表的是父类的定义,而不是父类对象
                  self.master = master
                  self.textpad = None             # textpad表示Text文本框对象
                  self.pack()
                  self.createWidget()
              def createWidget(self):
                  # 创建主菜单栏
                  menubar = Menu(root)
                  # 创建子菜单
                  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.test)
                  menuFile.add_command(label="打开", accelerator="ctrl+o", command=self.test)
                  menuFile.add_command(label="保存", accelerator="ctrl+s",command=self.test)
                  menuFile.add_separator()  # 添加分割线
                  menuFile.add_command(label="退出", accelerator="ctrl+q",command=self.test)
                  # 将主菜单栏加到根窗口
                  root["menu"] = menubar
                  #文本编辑区
                  self.textpad = Text(root, width=50, height=30)
                  self.textpad.pack()
                  # 创建上下菜单
                  self.contextMenu = Menu(root)
                  self.contextMenu.add_command(label="背景颜色", command=self.test)
                  #为右键绑定事件
                  root.bind("",self.createContextMenu)
              def test(self):
                  pass
              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(master=root)
              root.mainloop()
          

          运行

          python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          在记事本中,右键可以显示背景颜色

          3.【项目】记事本软件开发

          结合所学 GUI 知识,开发一款模仿 windows 记事本的软件。包含了基本的功能:

          1. 新建文本文件
          2. 保存文件
          3. 修改文件内容
          4. 退出
          5. 各种快捷键处理
          6. 修改文本区域背景色
          """开发记事本软件的菜单
          """
          from tkinter import *
          from tkinter.filedialog import *
          from tkinter.colorchooser import *
          from tkinter import messagebox
          class Application(Frame):
              def __init__(self, master=None):
                  super().__init__(master)        # super()代表的是父类的定义,而不是父类对象
                  self.master = master
                  self.textpad = None             # textpad表示Text文本框对象
                  self.filename = None
                  self.pack()
                  self.createWidget()
              def createWidget(self):
                  # 创建主菜单栏
                  menubar = Menu(root)
                  # 创建子菜单
                  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("",lambda event:self.newfile())
                  root.bind("",lambda event:self.openfile())
                  root.bind("",lambda event:self.savefile())
                  root.bind("",lambda event:self.exit())
                  #文本编辑区,多行文本
                  self.textpad = Text(root, width=50, height=30)
                  self.textpad.pack()
                  # 创建上下菜单
                  self.contextMenu = Menu(root)
                  self.contextMenu.add_command(label="背景颜色", command=self.openAskColor)
                  #为右键绑定事件
                  root.bind("",self.createContextMenu)
              def newfile(self):
                  #如果是第一次新建,就新建新文本,如果是打开程序直接点击保存,就把写进去的内容保存起来
                  if self.filename:
                      self.textpad.delete("1.0", "end")  # 把text控件中所有的内容清空
                      self.filename= asksaveasfilename(,initialfile="未命名.txt",
                                        filetypes=[("文本文档","*.txt")],
                                        defaultextension=".txt")
                      #判断是否新建,如果未新建,则不用保存
                      if self.filename:
                          self.savefile()
                      else:
                          self.destroy()
                  else:
                      self.filename= asksaveasfilename(,initialfile="未命名.txt",
                                        filetypes=[("文本文档","*.txt")],
                                        defaultextension=".txt")
                      #判断是否新建,如果未新建,则不用保存
                      if self.filename:
                          self.savefile()
                      else:
                          self.destroy()
              def openfile(self):
                  self.textpad.delete("1.0","end")        # 把text控件中所有的内容清空
                  # with askopenfile() as f: 别这样用,否则当没有打开文件时,会有个报错
                  f = askopenfile()
                  print("打开的文件对象是:",f)
                  #如果有打开,则在将写入的插入,没打开不用插入,在光标所在处插入文本内容
                  if f:
                      self.textpad.insert(INSERT,f.read())
                      #将打开之后的文件名赋值给self.filename
                      self.filename = f.name
                  else:
                      self.destroy()
              #实现保存方法
              def savefile(self):
                  #第一次打开程序,直接点击保存bug修复
                  print("第一次打开程序点击保存",self.filename)
                  if self.filename:
                      f = open(self.filename,"w")
                      if f:
                          #获取到文本内容字符串,然后在通过open保存
                          c = self.textpad.get(1.0,END)
                          f.write(c)
                  else:
                      # messagebox.showinfo("Warning", "请先新建文件!")
                      self.newfile()
              def exit(self):
                  root.destroy()
              def openAskColor(self):
                  s1 = askcolor(color="red",)
                  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(master=root)
              root.mainloop()
          

          运行

          python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          点击文件-新建

          python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          修改文件名

          python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          点击保存,保存到了桌面

          python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          点击文件-打开

          python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          随便写点东西

          python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          点击文件-保存,查看文件,内容已被保存进去

          python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          askopenfile返回的文件对象解析,里面的name即为包含路径的文件名字符串

          python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          修改文本背景色,在文本域右键,背景颜色

          python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          选一个背景色

          python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          4.【项目】画图软件开发

          开发一款简单的画图软件, 包含如下功能:

          1. 画笔
          2. 矩形/椭圆绘制
          3. 清屏
          4. 橡皮擦
          5. 直线/带箭头的直线
          6. 修改画笔颜色、背景颜色
          """开发画图软件的菜单
          """
          from tkinter import *
          from tkinter.colorchooser import *
          #窗口的宽度和高度
          win_width=900
          win_height=450
          class Application(Frame):
              def __init__(self, master=None,bgcolor="#000000"):
                  super().__init__(master)        # super()代表的是父类的定义,而不是父类对象
                  self.master = master
                  self.bgcolor=bgcolor
                  self.x = 0
                  self.y = 0
                  self.fgcolor = "#ff0000"
                  self.lastDraw = 0               # 表示最后绘制的图形的id
                  self.startDrawFlag = False
                  self.pack()
                  self.createWidget()
              def createWidget(self):
                  # 创建绘图区
                  self.drawpad = Canvas(root,width=win_width,height=win_height*0.9,bg=self.bgcolor)
                  self.drawpad.pack()
                  #创建按钮,并给每个按钮定义一个名字,好区分
                  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_oval = Button(root,text="椭圆",name="oval")
                  btn_oval.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","",self.eventManager)
                  #释放按键事件
                  self.drawpad.bind("",self.stopDraw)
                  #增加颜色切换的快捷键
                  root.bind("",self.kuaijiejian)
                  root.bind("",self.kuaijiejian)
                  root.bind("",self.kuaijiejian)
              def eventManager(self,event):
                  #获取根据名字获取相关按钮
                  name = event.widget.winfo_name()
                  # print("获取widget:", dir(event.widget))
                  print(name)
                  if name=="line":
                      self.drawpad.bind("",self.myline)
                  elif name=="lineArrow":
                      self.drawpad.bind("",self.mylineArrow)
                  elif name=="rect":
                      self.drawpad.bind("",self.myRect)
                  elif name == "oval":
                      self.drawpad.bind("", self.myOval)
                  elif name=="pen":
                      self.drawpad.bind("",self.myPen)
                  elif name=="erasor":
                      self.drawpad.bind("",self.myErasor)
                  elif name=="clear":
                      #清屏,直接delete("all")
                      self.drawpad.delete("all")
                  elif name=="color":
                      c = askcolor(color=self.fgcolor,)
                      #[(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)
                  #矩形边框颜色 outline
                  self.lastDraw = self.drawpad.create_rectangle(self.x,self.y,event.x,event.y,outline=self.fgcolor)
              def myOval(self,event):
                  self.startDraw(event)
                  #椭圆边框颜色 outline
                  self.lastDraw = self.drawpad.create_oval(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(master=root)
              root.mainloop()
          

          运行

          python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

          可以根据各个按钮,实现不同功能

          python GUI开发: tkinter菜单创建,记事本和画图软件综合项目的实战演练

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]