Vasilis Vlachoudis | 25 Aug 16:15 2014

Text() highlight

Hi all,

I am trying to implement a small g-code editor and real time viewer in tkinter.
I am using the Text() widget as an editor, but I have troubles
in highlighting the text during editing. Its slow when editing big files.

below is the highlighting routine

The routine is scanning for all patterns and picks the next one to highlight
(found dictionary). It assigns a tag and re-scans all the tags that
became invalid (falling within the area of the the just assigned tag.
e.g. a valid command inside a comment)

Running it on the whole text file on every modification is out of the question,
it makes the editing very very slow on big files.

In order to minimize the calls, I do them with a delay of 50ms, using the after()
command during a period of inactivity and only for the 100lines following
the first one to be displayed. Still is slow and lacks interactivity.

I  would like your suggestions, on what is the best way to do the highlighting
during the editing of the code?

Thanks in advance

     def highlight(self):
        self._highAfter = None
        # List contains order of match with regular expression
        patterns = {"C": (r"\(.*\)",              "Blue")    ,
                "X": (r"[xX][+\-]?\d*\.?\d*", "DarkRed"  ),
                "Y": (r"[yY][+\-]?\d*\.?\d*", "DarkBlue" ),
                "Z": (r"[zZ][+\-]?\d*\.?\d*", "DarkGreen"),

                "I": (r"[iI][+\-]?\d*\.?\d*", "Maroon"),
                "J": (r"[jJ][+\-]?\d*\.?\d*", "Maroon"),
                "K": (r"[kK][+\-]?\d*\.?\d*", "Maroon"),
                "R": (r"[rR][+\-]?\d*\.?\d*", "Maroon"),

                "G": (r"[gG]\d+",             "Dark Orchid"),
                "M": (r"[mM]\d+",             "DarkGrey"),
                "F": (r"[fF][+\-]?\d*\.?\d*", "Yellow4"),
                "P": (r"[pP]\d+",             "DarkGrey") }

        for tag in patterns.keys():

        count = IntVar()
        start = self.editor.index("%d.0"%(self._highStart))
        end   = self.editor.index("%d.0"%(self._highStart+100))

        # First search for the first occurance of all patterns
        found = {}
        for tag,(pat,color) in patterns.items():
            index =, start, end, count=count, regexp=True)
            if index != "":
                found[tag] = (index, count.get())
                #print "Found:", tag, index, count.get()

        # Main loop
        while True:
            # Find the top-most pattern to highlight
            nextTag   = None
            nextIndex = end
            nextCount = 0
            for tag,(index,c) in found.items():
                    nextTag   = tag
                    nextIndex = index
                    nextCount = c

            #print "Minimum:", nextTag, nextIndex, nextCount
            if nextTag is None: break
            start = self.editor.index("%s+%sc"%(nextIndex,nextCount))
            self.editor.tag_add(nextTag, nextIndex, start)

            # Update tags
            foundItems = found.items()
            for tag,(index,c) in foundItems:
                #print ">>",tag,index
                    index =[tag][0],
                            start, end,
                    if index != "":
                        #print "Update:", tag, index, count.get()
                        found[tag] = (index, count.get())
                        #print "Update:", tag, "-None-"
                        del found[tag]

        # Set properties to tags
        for tag,(pat,color) in patterns.items():

    # ----------------------------------------------------------------------
    def highlightAfter(self):
        if self._highAfter is not None: self.after_cancel(self._highAfter)
        self._highAfter = self.after(10, self.highlight)

Tkinter-discuss mailing list
Tkinter-discuss <at>
JBB | 12 Aug 05:37 2014

tkFileDialog.askopenfile() mac


I am attempting to use tkFileDialog.askopenfile():

1) On my Mac OSX Mavericks w/ Python 2.7.8, Anaconda 2.0.1 (x86_64) the 
following code (found via web searches) crashes:

from Tkinter import *
import tkFileDialog
root = Tk()
file = tkFileDialog.askopenfile(parent=root)

- A file dialog opens, I can select a file and click the Open button or 
doubleclick the filename.  The window freezes, the spinning rainbow ball 
comes up, and a Kernel restart is needed to close the window.

This happens on iPython notebook as well as within the Spyder IDE.

2) I run the same distribution on a Linux VM on the same machine. 
There, it works fine.  The variable 'file' contains the name of 
whichever file I've selected.

As far as I know, my Mac Python distribution is up-to-date.

Pointers to documentation or fixes appreciated.

Bob Greschke | 19 Jul 00:54 2014

Combining events?

I have a huge program...several huge programs...and I keep writing duplicate sets of calls for <Return>
and <KP_enter>.  I'm tired of it, even though they are already all written.  Is there any way to combine those
(those two, specifically) into one bind like

x.bind(("<Return>", "<KP_Enter"), command = .....?

I know you can't do that, but something like that on a global scale (both figuratively, and
programmatically).  Some little line of code at the beginning of the program that redirects the
<KP_Enter> to the <Return> event when some field or whatever is specifically looking for either return
key to be pressed?.

Alan Gauld | 23 Jun 00:18 2014

divergent behaviour

I've observed a strange difference in the behaviour of
one of my event handlers, I'm wondering if anyone knows
the explanation.

I have a form with a list box and a set of buttons.
When you highlight a list item you can press the
Edit button and it calls evEdit() which opens an
edit dialog in the centre of the parent window.

However I also bound the double click event to evEdit and
if you double click the same item it opebns the dialog
in the centre of the screen.

Does anyone know why double-click and button versions
of the same method result in different locations? I'm
assuming that somehow the dialog (TopLevel widget) sees
the screen as its parent in one version but the
original window as parent in the other - maybe...?

If necessary I'll try to produce a short example to
illustrate, but the existing code is over 500 lines
so a tad too long to post.


Alan G
Author of the Learn to Program web site
Thiago Padilha | 10 Jun 23:59 2014

Text widget "lags" when doing fast updates with increased window heights

I'm currently implementing a sample UI for neovim(,
and decided to use Tkinter/python due to the popularity/simplicity of
the platforms. The problem I'm having is that tkinter seems to "stack"
UI updates when the window height crosses a certain threshold.

Here is a video that shows the problem:

The right window is a terminal emulator running neovim, and the left
window is the Tkinter UI program connected to neovim. The idea is that
the tkinter UI should mirror neovim terminal screen, including
dimensions. Notice that in this video I don't take focus away from the
terminal window, so the only events Tk has to process come from the
connection to neovim(virtual <<nvim>> events which describe screen

The first part of the video shows that everything works nicely when
the window height is small, but starts to lag updates when I increase
the height.

I think what I'm trying to implement is close to a terminal
emulator(must handle large bursts of text updates efficiently) but I'm
very inexperienced in GUI programming. Is Tkinter a wise choice for
this task? If yes, then what am I doing wrong?(

The code for the Tkinter program is here:
and my OS is ubuntu 12.04(running as a VM under windows 7)

Thanks in advance

Saimadhav Heblikar | 8 Jun 15:55 2014

About making Text.tag_*range methods more consistent

Some code,

>>> from tkinter import Text
>>> text = Text()
>>> text.pack()
>>> text.insert('insert', 'ab cd ef')
>>> text.tag_add('red', '1.0','1.2')
>>> text.tag_add('red', '1.6', '1.8')
>>> text.tag_prevrange('red', 'end')
('1.6', '1.8')
>>> text.tag_ranges('red')
(<textindex object: '1.0'>, <textindex object: '1.2'>, <textindex object: '1.6'>, <textindex object: '1.8'>)
>>> text.tag_nextrange('red', '1.0')
('1.0', '1.2')

I propose that Text.tag_ranges(tag) return a list of tuples (start index, end index), instead of a list like [start index1, endindex1, startindex2, endindex2....etc]

To be more even more consistent, tag_ranges tuples should contain indexes similar to the ones returned by tag_prevrange/tag_nextrange i.e. strings instead of textindex objects.

So, the above output would have been
>>> text.tag_ranges('red')
(('1.0', '1.2'), ('1.6', '1.8'))

If there is a reason for current behavior, can you link me to it?
Saimadhav Heblikar
Tkinter-discuss mailing list
Tkinter-discuss <at>
Alan Gauld | 13 May 20:51 2014

How to enable/disable a menu?

I have an app with a tabbed notebook. I want to
only enable one of the main menus when the appropriate
tab is selected. When the tab is deselected I want
to disable the menu again.

I can't see any obvious properties in the Menu
object. I can mess around with flags in the event
handlers and change the menu font colours etc but
that's pretty horrible. Is there anything better?

Using Python 3.3; on Linux and Windows 8 if it makes
any difference.


Alan G
Author of the Learn to Program web site
Josef Eschgfaeller | 9 May 23:35 2014

Different fonts in 3.3?

Trying to pass from Python 3.1 to 3.3 I have
a problem with Tkinter: fonts (or spacings)
in 3.3 seem to be higher, so that after
instructions like


the text widget requires more space than
before with 3.1. I have Mac OS X 10.6.8 and
call Python from a script using

    #! /Library/Frameworks/Python.framework\

It seems also that the letters are a bit uglier,
somewhat more compressed.

Josef Eschgfaeller
Alan Gauld | 20 Apr 19:30 2014

Is this the right place for Tix questions?

I don't see a separate Tix group so is this a valid place
to ask Tix questions? I've been trying to use some of
the Tix widgets and running into issues, especially
with tix.Grid formatting.


Alan G
Author of the Learn to Program web site
GKalman | 15 Mar 02:20 2014

Need help using Tkinter Widget lift() and lower() methods with Place geometry Manager

I tried a simple case:
Frame with two Canvas widgets. I drag (i.e. move) Canvas #1. When it
overlaps with Canvas #2 neither the lift() nor the lower() methods work.
from Tkinter import *

class myObject():
    def __init__(self,root):
        self.root = root

        #place a Frame on the root:
        self.f = Frame(self.root, bg="yellow", width=600, height=400)

        #place a Canvas on the Frame:
        self.c =Canvas(self.f, bg="cyan",width=100,height=50)
        #NW-vtx of Canvas:

        self.c.bind('<ButtonPress-1>', self.startMoveWindow)
        self.c.bind('<B1-Motion>', self.MoveWindow)


    def startMoveWindow(self, event):
        ## at start: record current root coordinates
        self.xo, self.yo = event.x_root, event.y_root

    def MoveWindow(self, event):

        ## use root coordinates for offset of Widget (canvas) coordinates
        self.xNW += event.x_root - self.xo
        self.yNW+= event.y_root - self.yo
        ## update coordinates
        self.xo, self.yo= event.x_root, event.y_root

        ## Move & redraw Widget (canvas)
        self.c.place_configure(x=self.xNW, y=self.yNW)

x = myObject(root)

View this message in context:
Sent from the Python - tkinter-discuss mailing list archive at
deepak | 12 Mar 18:08 2014

how to get values form the custom widget module to the parent frame widget in Tkinter?

I am ne to python GUi, I have built a cust frame by inheriting the Frame ,
the code is as follows :

    from Tkinter import *
    from logging import exception
    import tkFileDialog
    import  pickle
    import os.path



    class NAddStation(Frame):
        def __init__(self, parent=None):
            Frame.__init__(self, parent)
            self.pack(side=TOP, expand=YES, fill=BOTH)
            self.tempVar = []
            # Label Area
            self.labels = ["Station Name :", "Target Name  :", "Host Name   
:", "Target's IP  :", "Host's IP    :",
                           "Excel File   :"]
            self.REMOVE =1
            self.ADD = 2
            self.UPDATE = 3
            # Entry Area
            self.Entry_Target_Name = None
            self.Entry_Host_Name = None
            self.Entry_Target_IP = None
            self.Entry_Host_IP = None
            self.Entry_Station_Name = None
            self.Entry_File_Path = None

            self.File_Browse_Button = None
            self.Add_Button = None
            self.Cancel_Button = None

        def openFileBrowser(self):
            filepath = tkFileDialog.askopenfilename()
            self.Entry_File_Path.insert(0, filepath)

        def validate(self):
            print("Adding Data....")


        def Remove_Station(self,key):

            if  os.path.isfile('Station-pickle'):
                dbfile = open('Station-pickle', 'rb')
                db = pickle.load(dbfile)

                dbfile = open('Station-pickle', 'wb')
                pickle.dump(db, dbfile)

        def returnStationName(self):
            return self.tempVar[0].get()


        def Store_Station(self):
            fl['SN']= self.tempVar[0].get()
            fl['HN']= self.tempVar[1].get()
            fl['HP']= self.tempVar[2].get()
            fl['TN']= self.tempVar[3].get()
            fl['TP']= self.tempVar[4].get()
            fl['XL']= self.tempVar[5].get()
            station_name = self.tempVar[0].get()
            rc[station_name]= fl
            if not os.path.isfile('Station-pickle'):
                print ("Creating File")
                dbfile = open('Station-pickle', 'wb')               # use
binary mode files in 3.X
                pickle.dump(rc, dbfile)                            # data is
bytes, not str
                print ("Appending File")
                # --------
                dbfile = open('Station-pickle', 'rb')
                db = pickle.load(dbfile)
                db[station_name] = fl
                dbfile = open('Station-pickle', 'wb')
                pickle.dump(db, dbfile)


        def Load_Station(self, key_value):
            dbfile = open('Station-pickle', 'rb')               # use binary
mode files in 3.X
            db = pickle.load(dbfile)
            for key in db:
                if key == key_value:
                    print("STATION_NAME  :" +  db[key]['SN'])
                    print("HOST_NAME     :" +  db[key]['HN'])
                    print("HOST_IP       :" +  db[key]['HP'])
                    print("TARGET_NAME   :" +  db[key]['TN'])
                    print("TARGENT_IP    :" +  db[key]['TP'])
                    print("FILE_NAME     :" +  db[key]['XL'])
                    return ("STATION_NAME  :" +  db[key]['SN'] +"\n" +
"HOST_NAME     :" +  db[key]['HN'] + "\n" + "HOST_IP       :" + 
db[key]['HP'] + "\n" + "TARGET_NAME   :" +  db[key]['TN'] + "\n" +
"TARGENT_IP    :" +  db[key]['TP'] + "\n" + "FILE_NAME     :" + 
            print "No Station with Name " + key_value




        def createWindow(self):
            # Station Entry
            Label(self, text=self.labels[STATION_NAME]).grid(row=0,
            self.Entry_Station_Name = Entry(self, width=20)
            self.Entry_Station_Name.grid(row=0, column=1)
            # Host Entry
            Label(self, text=self.labels[HOST_NAME]).grid(row=1, column=0)
            self.Entry_Host_Name = Entry(self, width=20)
            self.Entry_Host_Name.grid(row=1, column=1)
            Label(self, text=self.labels[HOST_IP]).grid(row=1, column=2)
            self.Entry_Host_IP = Entry(self, width=20)
            self.Entry_Host_IP.grid(row=1, column=3)

            # Target Entry
            Label(self, text=self.labels[TARGET_NAME]).grid(row=2, column=0)
            self.Entry_Target_Name = Entry(self, width=20)
            self.Entry_Target_Name.grid(row=2, column=1)

            Label(self, text=self.labels[TARGET_IP]).grid(row=2, column=2)
            self.Entry_Target_IP = Entry(self, width=20)
            self.Entry_Target_IP.grid(row=2, column=3)
            #Browser Button
            Label(self, text=self.labels[EXCEL_FILE]).grid(row=3, column=0)
            self.Entry_File_Path = Entry(self, width=50)
            self.Entry_File_Path.grid(row=3, column=1)
            self.File_Browse_Button = Button(self, text="Browse",
command=self.openFileBrowser, width=10,justify=CENTER).grid(row=3, column=3)
            Button(self, text="Add", command=(lambda : self.validate()),
width=10,justify=CENTER).grid(row=4, column=1)
            Button(self, text="Cancel", command=
self.winfo_toplevel().destroy, width=10,justify=CENTER).grid(row=4,

**Now I want to use the above mentioned Custom Frame in Main app , when i
ckick on AddStation  from menu file the custome Frame pops up , I can add
the data but when i click on ok , i want the data to apear on the textArea ,
represented by Self.Entity2 in the following code:**

    from Tkconstants import LEFT, BOTTOM, X, TOP, RIGHT, ACTIVE, Y
    from Tkinter import Tk, Frame, Menu, END, Label, YES, BOTH, Entry,
StringVar, Toplevel
    import Tkinter
    import sys
    from  make_db_pickle import *

    class SimpleApp(Frame):
        def __init__(self, parent):
            Frame.__init__(self, parent)
            self.parent = parent
            self.pack(expand=YES, fill=BOTH)
            self.TargetName = None
            self.HostName = None
            self.eHostNameEntry =None
            self.sbar = None
            self.AddWidget = None

        def CancelButtonPressed(self, widget):
            # print "Cancel Button Pressed"

        def AddEntryToListBox(self,entry):

            self.entry1.insert(END, entry)

        def enter(event,entry,widget):


        def OkButtonPressed(self,entry,widget):
            print "Ok bution pressed"

        def runCommand(self, selection):                       # redefine me
            self.entry2.insert('1.0',"The following Station was selected " +
            self.entry3.insert('1.0',"The following Station was selected " +
            self.entry4.insert('1.0',"The following Station was selected " +

            print('You selected:', selection)

        def handleList(self, event):
            index = self.entry1.curselection()                # on list
            label = self.entry1.get(index)                    # fetch
selection text
            self.runCommand(label)                             # and call
action here

        def initialize(self, parent):
            menubar = Menu(self.parent)
            self.sbar = Tkinter.Scrollbar(self)
            fileMenu = Menu(menubar, tearoff = False)
            fileMenu.add_command(label="Add Station",
            fileMenu.add_command(label="Delete Station",
            fileMenu.add_command(label="Exit", command=self.onExit)
            menubar.add_cascade(label="File", menu=fileMenu)

            self.entry1 = Tkinter.Listbox(self, height=24, yscrollcommand=1,
            # --------------------------
            self.sbar = Tkinter.Scrollbar(self)

            self.sbar.config(command=self.entry1.yview)                    #
xlink sbar and list
            self.entry1.config(yscrollcommand=self.sbar.set)               #
move one moves other

            self.entry1.pack(side=LEFT, expand=YES, fill=BOTH)        # list
clipped first
            # pos = 0
            #list.config(selectmode=SINGLE, setgrid=1)          #
select,resize modes
            self.entry1.bind('<Double-1>', self.handleList)           # set
event handler

            # --------------------------

            # for i in acts:
            #     self.entry1.insert(END, i)

            # self.entry1 = Tkinter.Text(self)
            self.entry1.grid(column=0, row=0, sticky='EW')

            self.entry2 = Tkinter.Text(self)
            self.entry2.grid(column=1, row=0, sticky='EW', padx=1, pady=1)

            self.entry3 = Tkinter.Text(self)
            self.entry3.grid(column=0, row=1, sticky='EW', padx=1, pady=1)

            self.entry4 = Tkinter.Text(self)
            self.entry4.grid(column=1, row=1, sticky='EW', padx=1, pady=1)

        def onExit(self):
        def AddNewStation(self):
            n = Toplevel(root)
            n.title("Add Station")
            self.AddWidget = NAddStation(n)

        def AddStation(self):
            AddStationDialogBox = Toplevel(root)  #Tkinter.Tk()

            AddStationDialogBox.title('Add Station')

            frame = Frame(AddStationDialogBox) #frame for target entry
            frame.pack(padx=10, pady=10,side=TOP,fill=X)

            bottomframe = Frame(AddStationDialogBox) #froame for host entry
            bottomframe.pack(padx=10, pady=10,side=TOP,fill=X)

            bottomframe2 = Frame(AddStationDialogBox) #frame for button

            lTargentName = Label(frame, text="Target Name :")
            TargetName = StringVar()
            eTargetEntryField = Entry(frame,width=20)

            lHostName = Label(bottomframe, text="Host Name  :")
            HostName = StringVar()
            eHostNameEntry = Entry(bottomframe,width=20)
            okbutton = Tkinter.Button(bottomframe2,
text="OK",command=(lambda : self.OkButtonPressed(eTargetEntryField,
            okbutton.pack(side=LEFT, padx=10, pady=15)

            cancelbutton = Tkinter.Button(bottomframe2, text="CANCEL",
command=(lambda : self.CancelButtonPressed(AddStationDialogBox)))
            cancelbutton.pack(side=LEFT, padx=10, pady=15)

            AddStationDialogBox.bind('<Return>',(lambda  event :

    if __name__ == "__main__":
        root = Tk()
        app = SimpleApp(root)


View this message in context:
Sent from the Python - tkinter-discuss mailing list archive at