之前在看tkinter与python编程 ,后面学opengl就把那本书搁置了。几天没用tkinter,怕是基本的创建组件那些都忘记了,所以想着用tkinter试着写一下记事本程序。一开始的时候以为很简单,真正写的时候才发现复杂得很。主要写着写着都没有耐心写下去了

另外这个程序使用了一些windows系统的特性,其他系统运行应该会出错吧...

from tkinter import *
import Pmw
import win32api
import win32con
import pywintypes
from PIL import Image,ImageTk
import tkinter.messagebox
import os
import glob
import tkinter.filedialog
import time

def create_topleve(title,width=500,height=500):
    topleve=Toplevel()
    topleve.title(title)
    topleve.geometry("{}x{}".format(width,height))
    #topleve.attributes("-toolwindow", 1)
    #topleve.transient(1)
    topleve.lift()
    hwnd = pywintypes.HANDLE(int(topleve.frame(), 16))

    style=win32api.GetWindowLong(hwnd,win32con.GWL_STYLE)&~win32con.WS_MAXIMIZEBOX&~win32con.WS_MINIMIZEBOX
    win32api.SetWindowLong(hwnd,win32con.GWL_STYLE,style)
    return topleve

#文件操作
file_name=""
#新建文件
def new_file():
    global file_name
    str=text.get(1.0,END)
    if len(str)!=1:
        r=tkinter.messagebox.askyesnocancel("记事本","检测到记事本中有输入内容,是否保存?")
        if r==TRUE:
            pass
        elif r==FALSE:
            file_name="无标题"
            root.title(file_name)
            text.delete(1.0,END)
        else:
            pass
    else:
        file_name="无标题"
        root.title(file_name)
        text.delete(1.0,END)


def open_file():
    global file_name
    file_name=tkinter.filedialog.askopenfilename(defaultextension = '.txt',initialdir="f:")
    if file_name=="":
        file_name="无标题"
    else:
        root.title(file_name)

        with open(file_name,"r") as f:
            try:
                text.delete(1.0,END)
                text.insert(1.0,f.read())
            except:
                file_name="无标题"
                tkinter.messagebox.showwarning("打开","打开文件出错")
                root.title(file_name)

def save_file():
    global file_name
    print(file_name)
    try:
        with open(file_name,"w") as f:
            f.write(text.get(1.0,END))
    except:
        save_file_as()

def save_file_as():
    global file_name
    file_path=tkinter.filedialog.asksaveasfilename(initialfile="*.txt",defaultextension=".txt",initialdir="f:")
    if file_path!="":
        file_name=file_path
        try:
            with open(file_name,"w") as f:
                f.write(text.get(1.0,END))
            root.title(os.path.basename(file_name))
        except:
            file_name="无标题"
            tkinter.messagebox.showwarning("打开","打开文件出错")
    else:
        pass
    root.title(file_name)

def set_pages():
    pass

def print_pages():
    pass

#退出
def exit_window():
    global root
    root.destroy()

#文本编辑

def e_undo():
    global text
    text.event_generate('<<Undo>>')

def e_cut():
    global text
    text.event_generate('<<Cut>>')

def e_copy():
    global text
    text.event_generate('<<Copy>>')

def e_paste():
    global text
    text.event_generate('<<Paste>>')

def e_del():
    global text
    text.event_generate('<<Clear>>')

def e_find():
    find_box=create_topleve("查找",height=50,width=410)
    f1=Frame(find_box)
    Label(f1,text="查找内容(N):").pack(side=LEFT,padx=10)
    var=StringVar()
    entry=Entry(f1,width=30,textvariable=var)
    entry.pack(side=LEFT,padx=10)
    Button(f1,text="确认查找",relief=GROOVE,borderwidth=2,command=lambda:find_text(var.get())).pack(side=LEFT,padx=10)
    f1.pack(side=TOP,pady=10)

def find_text(str):
    #print(str)
    countVar = StringVar()
    pos = text.search(str, "1.0", stopindex="end", count=countVar)
    text.tag_add("search", pos, "%s + %sc" %(pos, countVar.get()))
    text.tag_configure("search", background="orange")

def e_find_next():
    pass

def e_replace():
    pass

def e_goto():
    pass

def e_select_all():
    text.tag_add(SEL, "1.0", END)

def e_insert_date():
    text.insert(INSERT,time.ctime())


#设置字体
class ChoiceFont:
    def __init__(self):
        global font
        font="Gabriola"
        self.fontNames=self.getwinsysfont()
        self.root=create_topleve("设置字体",width=300,height=400)

        font_list=Pmw.ComboBox(self.root,label_text="选择字体",labelpos="wn",
                               listbox_width=30,dropdown=0,
                               selectioncommand=self.choseEntry,
                               scrolledlist_items=self.fontNames)
        font_list.pack(fill=BOTH,expand=1,padx=8,pady=8)

        Label(self.root,text="预览").pack(anchor=NW,padx=20)
        font_list.selectitem("Gabriola")

        self.str="Stray birds of summer come to my window to sing and fly away.And yellow leaves of autumn, which have no songs, flutter and fall there with a sign"
        self.show=Label(self.root,text=self.str,font=("Gabriola",10),padx=5,anchor="w",relief=SUNKEN,wraplength=250)
        self.show.pack(padx=20,pady=10,expand=1,fill=X)

        self.cancelbtn=Button(self.root,text="取消",command=self.close).pack(side=RIGHT,padx=20)
        self.okbtn=Button(self.root,text="确定",command=self.set_font_to_text).pack(side=RIGHT)

    def close(self):
        self.root.after(1, self.root.destroy)

    def choseEntry(self,entry):
        self.show.configure(font="%s 10"%entry)

        font=entry

    def set_font_to_text(self):
        try:
            text.tag_add("selectedtext",SEL_FIRST,SEL_LAST)
            text.tag_config("selectedtext", font=font)
            #print(font)
        except:
            #tkinter.messagebox.showwarning("提示","未选中文本,请先选中文本再操作")
            pass
        self.close()

    def getwinsysfont(self):
        font_abspaths=glob.glob(r"C:\Windows\Fonts\*.*")
        font_relpaths=[]
        font_names=[]
        for font_abspath in font_abspaths:
            font_relpaths.append(font_abspath.split("\\")[-1])

        for font_relpath in font_relpaths:
            (font_name,ext)=os.path.splitext(font_relpath)
            font_names.append(font_name)
        return font_names

#设置其他格式

def set_more_format(n):
    try:
        text.tag_add("selectedtext",SEL_FIRST,SEL_LAST)
        if n==1:
            text.tag_config("selectedtext", underline=TRUE)
        if n==2:
            text.tag_config("selectedtext", overstrike=TRUE)
    except:
        #tkinter.messagebox.showwarning("提示","未选中文本,请先选中文本再操作")
        pass


def destroy_topleve(master):
    master.after(1,master.destroy())


#关于框
def about_program():
    about_topleve=create_topleve("关于")

    cv_about=Canvas(about_topleve)
    cv_about.pack(fill=BOTH,expand=1)

    im=Image.open("icon_max.png")
    global img
    img=ImageTk.PhotoImage(im)

    ad_f1=Frame(cv_about)
    ab_icon=Label(ad_f1,image=img,)#compound=CENTER
    ab_icon.pack(side=LEFT)
    ab_name=Label(ad_f1,text="Tkinter记事本程序",font=("Cambria 28"),fg="orange")
    ab_name.pack(side=LEFT)

    ad_f1.pack(side=TOP,pady=30)


    ad_f2=Frame(cv_about)
    Label(ad_f2,text="本记事本程序基于python tkinter编写",anchor=W).pack(side=TOP,expand=1,fill=X)
    Label(ad_f2,text="版本:tkinter记事本程序1.0 ©2019 vocus",anchor=W).pack(side=TOP,expand=1,fill=X)
    Label(ad_f2,text="本程序为python界面制作学习测试程序,无申明版权",anchor=W).pack(side=TOP,expand=1,fill=X)

    ab_add=Label(ad_f2,text="喜欢Python的小伙伴,欢迎一起交流",anchor=W)
    ab_add.pack(side=TOP,expand=1,fill=X,pady=50)

    ad_f2.pack(side=TOP,padx=50)


    line1=cv_about.create_line((50,110,450,90),width=3,fill="#2ca657",smooth=TRUE)

    ab_button=Button(cv_about,text="确定",command=lambda master=about_topleve:destroy_topleve(master),width=20)
    cv_about.create_window(360,350,window=ab_button)




root=Tk();

#菜单
mubar=Menu(root)
file_operations=Menu(mubar,tearoff=0)
file_operations.add_command(label="新建(N)        Ctrl+N",command=new_file)
file_operations.add_command(label="打开(O)...     Ctrl+O",command=open_file)
file_operations.add_command(label="保存(S)        Ctrl+S",command=save_file)
file_operations.add_command(label="另存为(A)...         ",command=save_file_as)
file_operations.add_separator()
file_operations.add_command(label="页面设置(U)          ",command=set_pages,state=DISABLED)
file_operations.add_command(label="打印(P)...     Ctrl+P",command=print_pages,state=DISABLED)
file_operations.add_separator()
file_operations.add_command(label="退出(X)              ",command=exit_window)

mubar.add_cascade(label="文件(F)",menu=file_operations)

#编辑
edit_text=Menu(mubar,tearoff=0)
mubar.add_cascade(label="编辑(E)",menu=edit_text)
edit_text.add_command(label="撤销(U)             Ctrl+Z",command=e_undo)
edit_text.add_separator()
edit_text.add_command(label="剪切(T)             Ctrl+X",command=e_cut)
edit_text.add_command(label="复制(C)             Ctrl+C",command=e_copy)
edit_text.add_command(label="粘贴(p)             Ctrl+V",command=e_paste)
edit_text.add_command(label="删除(L)                Del",command=e_del)
edit_text.add_separator()
edit_text.add_command(label="查找(F)...          Ctrl+F",command=e_find)
edit_text.add_command(label="查找下一个(N)           F3",command=e_find_next,state=DISABLED)
edit_text.add_command(label="替换(R)...          Ctrl+H",command=e_replace,state=DISABLED)
edit_text.add_command(label="转到(G)...          Ctrl+G",command=e_goto,state=DISABLED)
edit_text.add_separator()
edit_text.add_command(label="全选(A)             Ctrl+A",command=e_select_all)
edit_text.add_command(label="时间/日期(D)            F5",command=e_insert_date)

#格式
format_text=Menu(mubar,tearoff=0)
mubar.add_cascade(label="格式(O)",menu=format_text)
format_text.add_command(label="自动换行(W)")
format_text.add_command(label="字体(F)",command=lambda:ChoiceFont())

format_text.add_separator()

fromat_text_more=Menu(format_text,tearoff=0)
format_text.add_cascade(label="更多>>",menu=fromat_text_more)
fromat_text_more.add_command(label="    下划线    ",command=lambda n=1:set_more_format(n))
fromat_text_more.add_command(label="    删除线    ",command=lambda n=2:set_more_format(n))



#查看
vision=Menu(mubar,tearoff=0)
mubar.add_cascade(label="查看(V)",menu=vision)
vision.add_command(label="状态栏(S)",command="",state=DISABLED)

#帮助
help_me=Menu(mubar,tearoff=0)
mubar.add_cascade(label="帮助(H)",menu=help_me)
help_me.add_cascade(label="查看帮助(H)")
help_me.add_separator()
help_me.add_cascade(label="关于记事本(A)",command=about_program)

text=Text(root,bg="white")
text.pack(expand=1,fill=BOTH)

#滚动条
text_scroll=Scrollbar(text,command=text.yview)
text.configure(yscrollcommand=text_scroll.set)
text_scroll.pack(side=RIGHT,fill=Y)

#检查输入状态
'''
def set_title(event):
    if file_name=="":
        root.title("无标题"+"*")
    else:
        root.title(file_name+"*")



text.bind("<<Modified>>",set_title)

#text.edit_modified()
'''


root.title("无标题")
root["menu"]=mubar
root.geometry("800x600")
root.mainloop();

程序引用图片

icon_max.png

总结一下:

1.显示处于编辑状态,<<Modified>>事件
2.添加下划线,删除线子菜单,应该是使用add_radiobutton
3.绑定快捷键
4.其他未完成的菜单功能,都禁用了

在编程上,想到哪写到哪,类和函数定义混用,也没有模块化。。

等等,还有其他的问题,以后如果有空,再来处理一下吧

程序运行

02-14 03:02