一个简单的文本编辑器

1 篇文章 0 订阅
1 篇文章 0 订阅

本文旨在采取界面与交互分离的方式构建一个基本的文本编辑器,目前仅完成了一半。目前有部分菜单逻辑交互方式借鉴了此片博文的方法http://m.blog.csdn.net/article/details?id=50669230

一、首先是主界面UI,完成界面整体需求布局--TestTextUI:

#! /usr/bin/env python
# -*- coding: utf-8 -*-
import PyTkinter
import tkinter
from tkinter import *
import Adaptive
import os
from tkinter.filedialog import *
font = Adaptive.monaco_font


class TestTextUI(object):
    def __init__(self, master=None):
        self.root = master
        '''
        1.create the up frame: text frame
        2.create the down frame: status frame
        '''
        self.editframe = PyTkinter.PyLabelFrame(self.root)
        self.infoframe = PyTkinter.PyLabelFrame(self.root, height=2)


        self.editframe.pack(fill=BOTH, expand=1)
        self.infoframe.pack(fill=X)


        '''
        create the edit frame
        '''
        self.number_editframe = PyTkinter.PyLabel(self.editframe,
                                                  width=4)
        self.content_editframe = PyTkinter.PyText(self.editframe,
                                                  width=120)
        #self.content_editframe.insert('1.0', 'hello world')


        self.number_editframe.pack(fill=Y, side=LEFT)
        self.content_editframe.pack(fill=BOTH, expand=1, side=RIGHT)


        '''
        create the info frame
        '''
        self.line_column_label = PyTkinter.PyLabel(self.infoframe,
                                                   text="Line ,Column ",
                                                   font=font,
                                                   height=2)
        self.line_column_label.pack(fill=X, side=LEFT)



#the test code
if __name__ == "__main__":
    root = tkinter.Tk()
    root.geometry('+120+50')
    ttUI = TestTextUI(master=root)
    ttUI.content_editframe.delete('1.0', END)
    ttUI.content_editframe.insert('1.0', 'hello world!')
    root.mainloop()

二、这里UI界面的控件进行了一定程度的重写,使之更加符合软件界面风格--PyTkinter


#! /usr/bin/env python
# -*- coding: utf-8 -*-

'''
initial the Tkinter component
'''

import tkinter

g_default_theme = "dark"

class PyButton(tkinter.Button):
    '''
    button component
    '''
    def __init__(self, master, theme=g_default_theme, **kv):
        self.theme = theme
        self.kv = kv
        self.temp = dict()
        self.choose_theme()
        tkinter.Button.__init__(self, master, self.temp)

    def choose_theme(self):
        if self.theme == "dark":
            #the dictionary of the color property
            dark_theme_dict = {
                                "activebackground": "#00B2EE",
                                "activeforeground": "#E0EEEE",
                                "bg": "#008B8B",
                                "fg": "#FFFFFF"
                }
            #for initialing the property of the color of button
            for key,value in dark_theme_dict.items():
                self.temp[key] = value
            #to fill the text of the component
            for key,value in self.kv.items():
                self.temp[key] = value

class PyLabel(tkinter.Label):
    '''
    Label component
    '''
    def __init__(self, master, theme=g_default_theme, **kv):
        self.theme = theme
        self.kv = kv
        self.temp = dict()
        self.choose_theme()
        tkinter.Label.__init__(self,master,self.temp)

    def choose_theme(self):
        if self.theme == "dark":
            dark_theme_dict = {
                                "bg":"#292929",
                                "fg":"#E0EEEE"
                }
            for key,value in dark_theme_dict.items():
                self.temp[key] = value

            for key,value in self.kv.items():
                self.temp[key] = value

class PyLabelFrame(tkinter.LabelFrame):
    '''
    Frame component
    '''
    def __init__(self, master, theme=g_default_theme, **kv):
        self.theme = theme
        self.kv = kv
        self.temp = dict()
        self.choose_theme()
        tkinter.LabelFrame.__init__(self,master,self.temp)

    def choose_theme(self):
        if self.theme == "dark":
            dark_theme_dict = {
                                "bg":"#292929",
                                "fg":"#1e90ff"
                }
            for key,value in dark_theme_dict.items():
                self.temp[key] = value

            for key,value in self.kv.items():
                self.temp[key] = value

class PyListbox(tkinter.Listbox):
    '''
    Listbox component
    '''
    def __init__(self, master, theme=g_default_theme, **kv):
        self.theme = theme
        self.kv = kv
        self.temp = dict()
        self.choose_theme()
        tkinter.Listbox.__init__(self,master,self.temp)

    def choose_theme(self):
        if self.theme == "dark":
            dark_theme_dict = {
                                "bg":"#292929",
                                "fg":"#1e90ff",
                                "selectbackground":"#00b2ee"
                }
            for key,value in dark_theme_dict.items():
                self.temp[key] = value

            for key,value in self.kv.items():
                self.temp[key] = value

class PyText(tkinter.Text):
    '''
    Listbox component
    '''
    def __init__(self, master, theme=g_default_theme, **kv):
        self.theme = theme
        self.kv = kv
        self.temp = dict()
        self.choose_theme()
        tkinter.Text.__init__(self,master,self.temp)


    def choose_theme(self):
        if self.theme == "dark":
            dark_theme_dict = {
                                "bg":"#292929",
                                "fg":"#1e90ff",
                                "selectbackground":"#00b2ee"
                }
            for key,value in dark_theme_dict.items():
                self.temp[key] = value


            for key,value in self.kv.items():
                self.temp[key] = value

class PyCheckbutton(tkinter.Checkbutton):
    '''
    Checkbutton component
    '''
    def __init__(self, master, theme=g_default_theme, **kv):
        self.theme = theme
        self.kv = kv
        self.temp = dict()
        self.choose_theme()
        tkinter.Checkbutton.__init__(self,master,self.temp)

    def choose_theme(self):
        if self.theme == "dark":
            dark_theme_dict = {
                                "bg":"#292929",
                                "fg":"#1e90ff",
                                "activebackground":"#292929",
                                "activeforeground":"#ffffff",
                                "selectcolor":"#292929"
                }
            for key,value in dark_theme_dict.items():
                self.temp[key] = value

            for key,value in self.kv.items():
                self.temp[key] = value
                
class PyRadiobutton(tkinter.Radiobutton):
    '''
    Radiobutton component
    '''
    def __init__(self, master, theme=g_default_theme, **kv):
        self.theme = theme
        self.kv = kv
        self.temp = dict()
        self.choose_theme()
        tkinter.Radiobutton.__init__(self,master,self.temp)

    def choose_theme(self):
        if self.theme == "dark":
            dark_theme_dict = {
                                "bg":"#292929",
                                "fg":"#1e90ff",
                                "activebackground":"#292929",
                                "selectcolor":"#292929"
                }
            for key,value in dark_theme_dict.items():
                self.temp[key] = value

            for key,value in self.kv.items():
                self.temp[key] = value

class PyEntry(tkinter.Entry):
    '''
    Entry component
    '''
    def __init__(self, master, theme=g_default_theme, **kv):
        self.theme = theme
        self.kv = kv
        self.temp = dict()
        self.choose_theme()
        tkinter.Entry.__init__(self,master,self.temp)

    def choose_theme(self):
        if self.theme == "dark":
            dark_theme_dict = {
                                "bg":"#292929",
                                "fg":"#1e90ff",
                                "insertbackground":"#e0eeee"
                }
            for key,value in dark_theme_dict.items():
                self.temp[key] = value

            for key,value in self.kv.items():
                self.temp[key] = value
                
#the test code      
if __name__ == "__main__":
    root = tkinter.Tk()
    PyButton(root, text="123",font=("Monaco",12)).pack()
    PyLabel(root, text="123",font=("Monaco",12)).pack()
    PyLabelFrame(root, text="123",font=("Monaco",12)).pack()


    listbox_0 = PyListbox(root, height=2, font=("Monaco", 15))
    listbox_0.pack()
    for i in range(2):
        listbox_0.insert("end", i)


    PyText(root, font=("Monaco", 15), height=3,width = 20).pack()
    PyCheckbutton(root, text="123", font=("Monaco", 15)).pack()
    
    radio_intvar = tkinter.IntVar()
    PyRadiobutton(root, text="001", variable=radio_intvar, value=0, font=("Monaco", 15)).pack()
    PyRadiobutton(root, text="002", variable=radio_intvar, value=1, font=("Monaco", 15)).pack()
    PyRadiobutton(root, text="003", variable=radio_intvar, value=2, font=("Monaco", 15)).pack()
    radio_intvar.set(1)
    
    PyEntry(root, font=("Monaco", 15)).pack()
    root.mainloop()
        

三、接下来需要将软件整体框架和菜单栏进行整合,这里我还不太清楚如何将菜单栏分离为一个class进行添加,整体的menu都直接依赖于root--TestTextV0.3

#! /usr/bin/env python
# -*- coding: utf-8 -*-
from TestTextUI import TestTextUI
from tkinter import *
from tkinter.filedialog import *
from MenuCommand import *
class TestText(object):
    #create a initial frame
    def __init__(self):     
        #create the base frame
  
        self.root = Tk()
        self.root.title('TestText')
        self.root.geometry('+120+60')
        #self.ttUI = TestTextUI(master=self.root)
        self.mc = MenuCommand()
        
        #create the menubar frame
        self.menubar = Menu(self.root, bg='purple')
        #create the filemenu frame
        self.filemenu = Menu(self.menubar, tearoff=0)
        self.filemenu.add_command(label='New File', accelerator='Ctrl+n',
                                  command=self.mc.newfile, underline=0)
        self.filemenu.add_command(label='Open File', accelerator='Ctrl+o',
                                  command=self.mc.openfile, underline=0)
        self.filemenu.add_command(label='Save', accelerator='Ctrl+s',
                                  command=self.mc.savefile, underline=0)
        self.filemenu.add_command(label='Save As', command=self.mc.saveasfile, underline=0)
        self.filemenu.add_separator()
        self.filemenu.add_command(label='Exit', accelerator='Ctrl+t',
                                  command=self.root.destroy, underline=0)       
        self.menubar.add_cascade(label='File', underline=0, menu=self.filemenu)
        #create the editmenu frame
        self.editmenu = Menu(self.menubar, tearoff=0)
        self.editmenu.add_command(label='Undo', accelerator='Ctrl+z',
                                  command=self.mc.undoedit, underline=0)
        self.editmenu.add_command(label='Redo', accelerator='Ctrl+z',
                                  command=self.mc.redoedit, underline=0)
        self.menubar.add_cascade(label='Edit', underline=0, menu=self.editmenu)
        #create the optionmenu frame
        self.optionmenu = Menu(self.menubar, tearoff=0)
        self.optionmenu.add_command(label='Configuration', command=self.mc.configText, underline=0)
        self.menubar.add_cascade(label='Options', underline=0, menu=self.optionmenu)
        #create the helpmenu frame
        self.helpmenu = Menu(self.menubar, tearoff=0)
        self.helpmenu.add_command(label='About', command=self.mc.aboutText, underline=0)       
        self.menubar.add_cascade(label='Help', underline=0, menu=self.helpmenu)


        self.root.config(menu=self.menubar)
        self.root.mainloop()


if __name__ == "__main__":
    TestText()


四、根据菜单功能需求添加菜单反馈函数集--MenuCommand

#! /usr/bin/env python
# -*- coding: utf-8 -*-
'''
menu command array
'''
from TestTextUI import TestTextUI
from tkinter.filedialog import *
class MenuCommand(object):
    def __init__(self):
        #print('Open MenuCommand')
        self.ttUI = TestTextUI()
        self.var = StringVar()
        pass
    def newfile(self):
        print("create a new file")


    def openfile(self):
        print("open a file")
        filetypes = [
                ("All Files", '*'),
                ("Python Files", '*.py', 'TEXT'),
                ("Text Files", '*.txt', 'TEXT'),
                ("Config Files", '*.conf', 'TEXT')]
        fobj = askopenfile(filetypes=filetypes)
        if fobj:
            self.ttUI.content_editframe.delete('1.0', END)
            self.ttUI.content_editframe.insert('1.0', fobj.read())


    def savefile(self):
        print("save a file")
        value = self.var.get().strip()
        if value:
            f = open(value, 'w')
            f.write(self.ttUI.content_editframe.get('1.0', END).strip() + '\n')
            f.close()
        else:
            self.saveasfile()


    def saveasfile(self):
        print("save as a renamefile")
        text_value = self.ttUI.content_editframe.get('1.0', END).strip()
        if text_value:
            fobj = asksaveasfile()
            if fobj:
                fobj.write(text_value + '\n')


    def undoedit(self):
        print("return last status")


    def redoedit(self):
        print("return next status")


    def configText(self):
        print("the configuration of the TextIdle")


    def aboutText(self):
        print("the TextIdle info")

#the test code
if __name__ == "__main__":
    mc = MenuCommand()
    mc.newfile()


以上就是个人目前完成的包含基础功能的文本编辑器的全部代码了,这里还有许多进行需要优化的功能,这里先简要列几条作为后期优化改进的方向:

1、完善菜单功能,尤其是configuration功能,满足个性化修改界面外观的需求,undo&redo的功能

2、完善路径填充功能,满足title显示文件路径的需求

3、完善行显示的功能,text左侧直接显示当前光标所在行,底部状态显示当前光标所在行列值

4、完善多文件显示/切换功能,菜单栏下方直接留出一栏显示当前已打开的文件

5、完善缓存/记忆功能,保障关闭软件后仍旧能够记忆已打开的文件,下次打开时仍旧可以显示

6、完善文本高亮显示功能,能够根据打开的文件类型对相应的关键之进行高亮显示

……


以上为个人完成的一个简单的文本编辑器及对后续更新的相关思考,欢迎交流和指正~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值