Using tk to create a text editor Using tk to create a text editor tkinter tkinter

Using tk to create a text editor


Absolutely. The tkinter text widget is remarkably powerful. Everything you mentioned can be done, and more. You can also implement code folding, embedded images, hyperlinks, undo, etc.

Here are some answers to related questions you might find helpful:


Not to be repetitive, since Bryan Oakley already answered this, but yes. And he's right. The text widget is extremely powerful. I've never seen another text widget that matches its breadth of features.

Tkinter is the most convenient GUI library I've ever found for making a text editor. Actually, I've been making one, myself, for a while. Are you interested in making one or are you looking for one already made with Tkinter?

For me, syntax highlighting and autocomplete aren't the most important features in a text editor. I care more about quick/convenient file/project access, launching/compiling/running programs, Unicode or special character input, widget color schemes, navigation key-bindings, tabs, and having all kinds of shortcuts for various wild tools that I like to make my life easier (and more fun). So, I'm actually just starting on syntax highlighting now (after already having done most of the other stuff). But, yes, syntax highlighting can be done in Tkinter.

Really, though, a lot of the features you might want in a text editor don't even require much to do with the GUI library. For instance, making it recognize what kind of file you're editing, so you can run your file with the correct program (or compile it with the correct compiler). That really has little to do with Tkinter.

Let me know if you want to chat in real-time about text editors.

The IDE that comes with Python, IDLE, seems to be written with Tkinter, too. Looking at the source code is sometimes helpful, but they tend to do things in a different way than I would personally recommend, although I'm sure some people like it more than the way I like things.

There are a few drawbacks to Tkinter, but they're better than the drawbacks I've seen with other GUI libraries, for my purposes. Some things require more work, but most also seem to offer more flexibility. Some things require less work, too. Impressively, Tkinter doesn't seem to have a lot of bugs, and most of the ones that exist can be programmed around. It's quite robust. It gets a bad rap, sometimes, for not having native widgets and not rendering fonts a certain way, but don't listen to people. The widgets are fine, whether or not they're native, and the fonts look great. If there ever was a problem with the fonts, I think they fixed it. Tell me if I'm wrong. Mine look perfect (exactly as they do in LibreOffice, if not better). Besides, the perks of Tkinter shouldn't be ignored. Tkinter is awesome.

Python's help() method will be your friend. Use it on classes and modules.

One of the best things about Tkinter is that it pretty much comes with Python. So, unlike something like WxPython (which isn't even on 3.x, although they're making something for it with another name), Tkinter will likely automatically be supported for all future releases of Python (until if/when they decide to replace it with something else—and I don't know that they will, unless they find something totally awesome). Plus, it's not a huge download.

Anyway, to get started, you'll want to learn about marks (especially the built-in ones) and tags. You'll likely use those a lot for a lot of stuff. These are important for accessing specific areas of text in your widget and doing things to them.

INSERT is a string, 'insert'. But, it's also a mark. Marks are variable indexes to mark a position. The 'insert' mark represents the index in your text widget where your text insert is. The beginning of your document is the index "1.0" not "0.0". 1 is row 1. 0 is character 0. I don't believe there's a mark for the beginning. You just use the index. The mark for the end is END (which is a string, 'end'). 'sel.first' and 'sel.last' represent the indexes at the beginning and end of selected text. SEL (or 'sel') is a tag. Tags are kind of like HTML tags in that they mark the beginning and end of things (and all the text in between). You can make your own tags to add text styles (like bold and italics, or just highlights, which could be useful for syntax highlighting). You can check a range of text to see if it has a certain tag. For instance,

SEL in self.myTextWidget.tag_names(INSERT)

Will return True if the character directly after (that is, at) the text insert is selected.

For marks, you can use some handy notation to get some handy index locations. For instance "insert wordstart" will give you the index for the beginning of whatever word the 'insert' mark is on. "insert+2c" will give you the position two characters after the insert. Anyway, there's lots of stuff like that.

If you're making a cross-platform application, you'll want to know that a few of the events are different on different platforms. So, check and make sure they all work.

You'll also want to realize that although some of the standard keyboard shortcuts in the text widget don't work (like Control-a doesn't select all) there actually are shortcuts. They're just different shortcuts. However, you can override them and make your own pretty easily:

    …    #We're doing both a and A to make sure it works properly when caps-lock is on.    #Control-Shift-a is different from Control-A despite how it may seem.    self.myTextWidget.bind("<Control-a>", self.select_all)    self.myTextWidget.bind("<Control-A>", self.select_all)def select_all(self, event):    self.myTextWidget.tag_add("sel", "1.0", "end-1c") #END actually goes beyond the end of the text, adding a new line (so, I subtract a character).    return "break" #If you want to override the default binding, you need to return "break"


Tkinter is fairly maliable, it can be used to accomplish a number of tasks on its own. I've actually made my own mini text editor using tkinter in python 2.7. It doesn't have the advanced functionality yet though. But I think this would be a good basis for your idea. Make sure you have python2.7 installed.

from Tkinter import * import tkFileDialogclass Files(Frame):    def __init__(self, parent):        Frame.__init__(self, parent)           self.parent = parent                self.initUI()    def initUI(self):        self.parent.title("File dialog")        self.pack(fill=BOTH, expand=1)        menubar = Menu(self.parent)        self.parent.config(menu=menubar)        fileMenu = Menu(menubar)        fileMenu.add_command(label="Save", command = self.save_command)        fileMenu.add_command(label="Open", command = self.onOpen)        menubar.add_cascade(label="File", menu=fileMenu)                self.txt = Text(self)        self.txt.pack(fill=BOTH, expand=1)    def onOpen(self):        ftypes = [('Python files', '*.py'), ('All files', '*')]        dlg = tkFileDialog.Open(self, filetypes = ftypes)        fl = dlg.show()        if fl != '':            text = self.readFile(fl)            self.txt.insert(END, text)    def readFile(self, filename):        f = open(filename, "r")        text = f.read()        return text    def save_command(self):        file = tkFileDialog.asksaveasfile(mode='w')        if file != None:                data = self.txt.get('1.0', END+'-1c')                file.write(data)                file.close()root = Tk()top = Frame(root)top.pack(fill=BOTH, expand=1)def build():    l = Label(top, text="test phrase")    l.pack(side="left")    ent = Entry(top)    ent.pack(side="left")bottom = Frame(root)bottom.pack()ex = Files(root)ex.pack(side="bottom")root.geometry("300x250+300+300")root.mainloop()