原项目:[Tkinter项目]Python Tkinter NotePad记事本项目实战
/?p=4
整体的功能是模仿记事本的一些基本简单设计,但是增加了工具栏的快捷方式。名字为PNote,“P”是指单词“penguin”(企鹅),简而言之,该记事本叫“企鹅记事本”,其icon就是使用一张小企鹅的表情包制成的,增添界面的趣味性。界面功能思维导图如下
提前找好工具栏的图片,图片的格式都为gif,大小一般为32x32或16x16。icon图片来源网站:/
,下载的时候把图片后缀改成gif就可以了。先建一个py文件,随意起一个记事本的名字,py文件和图片文件分开放,图片放在同目录下的img文件中。ico图片转化网站:/。将小企鹅表情包.jpg图片转换成尺寸大小32x32的icon图
记录工具:CSDN官网上的Markdown编辑器
根据想法中的思维导图整个应用程序的图形化界面分为四个part:菜单栏、工具栏、文本输入区域、右键弹出菜单,将组件代码分别写在这个四个方法中,其他的功能实现方法则另外处理
PS:此处的代码展示和源码文件的排版并不一致
#导入tkinter类库
from tkinter import *
from tkinter import filedialog, messagebox
k import Scrollbar, Checkbutton,Label,Button #tkk里面的组件会有所优化
import os
import sys
class PNote(Tk):#工具栏所用图片的名称icons = ["new_file","open_file","save","cut","copy","paste","undo","redo","find_text"]icon_res = []# 默认主题使用字典(背景色为白色,字体为黑色)、主题一(背景为企鹅灰,字体为深蓝色)、主题二(背景色为深蓝色、字体为白色)theme_color = {"Default":"#000000.#FFFFFF","Penguin Gray":"#222b34.#e7e4e3","Night Mode":"#FFFFFF.#222b34"}# 初始化操作def __init__(self): super().__init__() #继承父类的构造 #调用方法self.set_window() #调用界面窗口方法ate_menu_bar() #菜单栏ate_tool_bar() #工具栏ate_body() #文本输入区域ate_pop_menu() #弹出菜单
# 设置窗口界面def set_window(self):self.title("PNote") #标题max_width,max_height = self.maxsize() #宽高# 居中对齐,像素align_center = "800x600+%d+%d" % ((max_width-800)/2,(max_height-600)/2) ry(align_center)self.iconbitmap("./img/penguin.ico")#创建菜单栏def create_menu_bar(self):menu_bar = Menu(self)self['menu']=menu_bar#添加菜单栏项目#文件file_menu = Menu(menu_bar,tearoff=0)file_menu.add_command(label='新建',accelerator='Ctrl+N',commandw_file)file_menu.add_command(label='打开',accelerator='Ctrl+O',command=self.open_file)file_menu.add_command(label='保存',accelerator='Ctrl+S',command=self.save_file)file_menu.add_command(label='另存为',accelerator='Ctrl+Shift+S',command=self.save_as)file_menu.add_separator() #分割符file_menu.add_command(label='退出',accelerator='Alt+F4',commandit_notepad)menu_bar.add_cascade(label='文件',menu=file_menu)#文件菜单功能实现# 打开文件功能def open_file(self,event=None):#打开文件并进行类型设置input_file = filedialog.askopenfilename(filetypes=[("所有文件","*.*"),("文本文档","*.text")])if input_file:self.title("{}***NotePad".format(os.path.basename(input_file)))self.file_name = t_text.delete(1.0,END)with open(input_file,'r') as _t_text.insert(1.0,_ad())#文件的保存,是保存(替代)原有文本文件的内容,先读写文件def write_to_file(self,file_name):try:content = (1.0,END)with open(file_name,'w') as _file:_file.write(content)self.title("{}---NotePad".format(os.path.basename(file_name)))except IOError:messagebox.showerror("错误","文件保存失败!")def save_file(self,event=None):if not self.file_name:self.save_as() #避免保存出来的新建的问题else:self.write_to_file(self.file_name)#新建def new_file(self,event=None):self.title("新建---PNote")t_text.delete(1.0,END)self.file_name = None#另存为def save_as(self):input_file = filedialog.askopenfilename(filetypes=[("所有文件","*.*"),("文本文档","*.text")])if input_file:self.file_name= input_fileself.write_to_file(self.file_name)#退出def exit_notepad(self):if messagebox.askokcancel("退出","确定退出吗?"):self.destroy()if __name__ == '__main__':app = PNote()app.mainloop()
由于编辑的功能和工具栏差不多,所以会其方法放在body部分,但是“查找”功能在此单独说明
#在方法create_menu_bar(self)加入以下代码#编辑editor_menu = Menu(menu_bar,tearoff=0)"""撤销,恢复,剪切,复制,粘贴,查找,全选"""menu_bar.add_cascade(label='编辑',menu=editor_menu)editor_menu.add_command(label='撤销',accelerator='Ctrl+Z',command=lambda:self.handle_menu_action('撤销'))editor_menu.add_command(label='恢复',accelerator='Ctrl+Y',command=lambda:self.handle_menu_action('恢复'))editor_menu.add_separator()editor_menu.add_command(label='剪切',accelerator='Ctrl+X',command=lambda:self.handle_menu_action('剪切'))editor_menu.add_command(label='复制',accelerator='Ctrl+C',command=lambda:self.handle_menu_action('复制'))editor_menu.add_command(label='粘贴',accelerator='Ctrl+V',command=lambda:self.handle_menu_action('粘贴'))editor_menu.add_separator()editor_menu.add_command(label='查找',accelerator='Ctrl+F',command=self.find_text_dialog)editor_menu.add_command(label='全选',accelerator='Ctrl+A',command=self.select_all)
查找文本功能
#设置查找对话框def find_text_dialog(self):search_dialog = Toplevel(self)search_dialog.title('查找文本')#居中max_width,max_height = self.maxsize() #宽高align_center = "300x80+%d+%d" % ((max_width-300)/2,(max_height-80)/2) ry(align_center)sizable(False,False)Label(search_dialog,text='查找全部').grid(row=0,column=0,sticky='e')search_text = Entry(search_dialog,width=25)id(row=0,column=1,padx=2,pady=2,sticky="we")search_text.focus_set()#忽略大小写ignore_case_value = IntVar()Checkbutton(search_dialog,text="忽略大小写",variable=ignore_case_value).grid(row=1,column=1,sticky='e',padx=2,pady=2)Button(search_dialog,text='查找',command=lambda:self.search_result((),ignore_(),search_dialog,search_text)).grid(row=0,column=2,sticky="w"+"e",padx=1,pady=1)# 关闭查找文本对话框def close_search_dialog():t_text.tag_remove('match',1.0,END)search_dialog.destroy()search_dialog.protocol("WM_DELETE_WINDOW",close_search_dialog)return "break"# 查找的方法def search_result(self,key,ignore_case,search_dialog,search_box):t_text.tag_remove('match',1.0,END)matches_found = 0if key:start_pos = 1.0while True:start_pos = t_text.search(key,start_pos,nocase=ignore_case,stopindex=END)if not start_pos:breakend_pos = "{}+{}c".format(start_pos,len(key))t_text.tag_add('match',start_pos,end_pos)matches_found +=1start_pos = t_text.tag_config('match',foreground='white',background='green')search_box.focus_set()search_dialog.title("发现了%d个匹配项" % matches_found)# 全选def select_all(self):t_text.tag_add('sel',1.0,END)return "break"
视图的下拉列表包括显示行号和显示高亮当前行、主题选择,前两者用checkbutton组件实现图形化界面,后者使用radiobutton组件实现图形化界面
# 在方法create_menu_bar(self)加入以下代码#视图菜单view_menu = Menu(menu_bar,tearoff=0)menu_bar.add_cascade(label='视图',menu=view_menu)"""显示行号"""self.is_show_line_num = IntVar()self.is_show_line_num.set(1)view_menu.add_checkbutton(label="显示行号",onvalue=0,offvalue=1,variable=self.is_show_line_num,command=self.update_line_num)"""显示高亮当前行"""self.is_heighlight_line = IntVar()view_menu.add_checkbutton(label="高亮当前行",variable=self.is_heighlight_line,commandle_highlight)"""主题"""themes_menu = Menu(menu_bar,tearoff=0)view_menu.add_separator()view_menu.add_cascade(label="主题",menu=themes_menu)#主题选择#默认主题self.theme_choice = StringVar()self.theme_choice.set("Default")for k in sorted(self.theme_color):themes_menu.add_radiobutton(label=k,variable=self.theme_choice,command=self.change_theme)#关于菜单about_menu = Menu(menu_bar,tearoff=0)about_menu.add_command(label="关于",command=lambda:self.show_messagebox("关于"))about_menu.add_command(label="帮助",command=lambda:self.show_messagebox("帮助"))menu_bar.add_cascade(label='关于',menu=about_menu)
“关于”菜单的下拉列表都是使用messagebox弄两个对话框,简单化,如图所示
# 主题的切换def change_theme(self):selected_theme = self.()fg_bg = self.(selected_theme)fg_color,bg_color = fg_bg.split('.')fig(bg=bg_color,fg=fg_color)# 关于菜单def show_messagebox(self,type):if type == "帮助":messagebox.showinfo("帮助","这是帮助文档",icon="question")else:messagebox.showinfo("关于","这是一个简单的记事本程序")
工具栏的,设计上是新建、打开、保存、剪切、复制、粘贴、撤销、重做、查找文本的icon逐一排列,和弹出菜单、菜单栏的功能是有些重复,是常用的功能快捷方式
def create_tool_bar(self):tool_bar = Frame(self,height=25,background="#ffffff") # 容器Frame,白色# 填充x轴tool_bar.pack(fill="x")# 生成图片文件放到对应的位置for icon in self.icons:tool_icon = PhotoImage(file="./img/%s.gif" % (icon,)) # 因为是元组所以有个逗号tool_btn = Button(tool_bar,image=tool_icon,commandl_bar_action(icon))tool_btn.pack(side="left") # 图片左对齐# 将tool_icon添加到icon_res里self.icon_res.append(tool_icon)
def tool_bar_action(self,action_type): def handle():if action_type == 'open_file':self.open_file()elif action_type == "save":self.save_file()elif action_type == "new_file":w_file()elif action_type == "cut":self.handle_menu_action("剪切")elif action_type == "copy":self.handle_menu_action("复制")elif action_type == "paste":self.handle_menu_action("粘贴")elif action_type == "undo":self.handle_menu_action("撤销")elif action_type == "redo":self.handle_menu_action("恢复")elif action_type == "find_text":self.find_text_dialog()# handle返回处理return handle
def create_body(self):# 左:行号;右:滚动条;中:文本编辑区# 行号区域self.line_number_bar = Text(self,width=3, padx=3,takefocus=0,border=0,background="#f0f0f0",state="disable") #state="disable"不能编辑状态#左边填充整个y轴self.line_number_bar.pack(side='left',fill='y')# 文本编辑区# undo=True是否具备文本取消功能,wrap:如何换行,word:按照单词自动换行,expand:可以拉伸t_text = Text(self,wrap="word",undo=True)# 热键绑定t_text.bind("<Control-o>",self.open_t_text.bind("<Control-O>",self.open_t_text.bind("<Control-s>",self.save_t_text.bind("<Control-S>",self.save_t_text.bind("<Control-n>",w_t_text.bind("<Control-N>",w_t_text.bind('<Any-KeyPress>',lambda e:self.update_line_num())t_text.pack(fill='both',expand="yes")# 设置文本输入区t_text.tag_config("active_line",background="#ffffff")# 滚动条scroll_bar = t_text)scroll_bar['command'] = t_t_text["yscrollcommand"] = scroll_bar.setscroll_bar.pack(side="right",fill="y")
# 行号处理def update_line_num(self):if self.is_show_():# 获取所有行row,col = t_text.index(END).split('.')# 列举每行的行号line_num_content = "n".join([str(i) for i in range(1,int(row))])self.line_fig(state="normal")self.line_number_bar.delete(1.0,END)self.line_number_bar.insert(1.0,line_num_content)self.line_fig(state='disable')else:self.line_fig(state='normal')self.line_number_bar.delete(1.0,END)self.line_fig(state='disable')
高亮的颜色默认是白色的,所以在
# 高亮当前行def toggle_highlight(self):if self.is_():t_text.tag_remove('active_line',1.0,END)# 设置高亮t_text.tag_add("active_line","insert linestart","insert lineend+1c")# 通过递归的方式进行处理,会很耗资源,想想有没有别的办法t_text.after(le_highlight)t_text.tag_remove("active_line",1.0,END)
弹出菜单的功能选项有:剪切、复制、粘贴、撤销、恢复、全选
#弹出菜单(也叫右键菜单)def create_pop_menu(self):pop_menu = t_text,tearoff=0)for item1,item2 in zip(['剪切','复制','粘贴','撤销','恢复'],['cut','copy','paste','undo','redo',]):pop_menu.add_command(label=item1,compound='left',commandl_bar_action(item2))pop_menu.add_separator() #分割pop_menu.add_command(label="全选",command=self.select_all)#绑定t_text.bind("<Button-3>",lambda event:pop_menu.tk_popup(event.x_root,event.y_root))#右键菜单的处理def handle_menu_action(self,action_type):if action_type == "撤销":t_text.event_generate("<<Undo>>")elif action_type == "恢复":t_text.event_generate("<<Rndo>>")elif action_type == "剪切":t_text.event_generate("<<Cut>>")elif action_type == "复制":t_text.event_generate("<<Copy>>")elif action_type == "粘贴":t_text.event_generate("<<Paste>>")#防止事件传递return "break"
版本如以下动图所示:
网上找的教程python打包生成exe可执行文件
打包使用的是auto -py-to-exe
先安装pip install auto-py-to-exe,安装成功后输入auto-py-to-exe回车会弹出一个窗口
根据网上的教程为了便于打包,修改了图片的位置,所以修改了代码中图片的路径表达,
self.iconbitmap("D:\PNote\img\penguin.ico")
tool_icon = PhotoImage(file="D:\PNote\img\%s.gif" % (icon,))
最后上传文件和图片
最中得到,测试使用无误
本文发布于:2024-02-01 14:18:21,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170676830137197.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |