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
(Continue reading)

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

(Continue reading)

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
memilanuk | 11 Mar 04:27 2014

importing tk.W?

So... this is kind of twisting my brain a bit.  Not sure I understand 
how/why this works the way it does.  Some help or explanation would be 

On the one hand, I keep reading about the evils/perils of wildcard 
imports and recommendations for named imports.  On the other hand, it 
seems like nearly every tkinter example in books, guides, tutorials that 
I see uses a wildcard import.

So I was trying to follow along some code examples from a recent book, 
and also trying to use python3 as much as practical.  Given that the 
original book code was python 2.x and I had to change 'Tkinter' to 
'tkinter', I figured why not change to using a named import, i.e.

import tkinter as tk

rather than

from Tkinter import *

Other than having to import a 'tk.' to widget names, I figured I should 
be good to go.  Unfortunately not.  The book had code like this:

from tkinter import *
root = Tk()
Label(root, text="Username").grid(row=0, sticky=W)

While what I was coming up with was more like this:

import tkinter as tk
root = tk.Tk()
tk.Label(root, text="Username").grid(row=0, sticky='W')

The difference being that unless I enclosed the W attribute for the 
option 'sticky=' in quotes, I got an error 'Unresolved reference 'W''.

I asked online, and found that apparently 'W' is imported along with 
'Label', 'Entry', 'Button', 'Tk', etc. at the top level of tkinter.  It 
appears I can use either a wildcard import, enclose it in quotes, or use 
explicit reference e.g. tk.W.

My question is this:  How / why does this make any sense, that an 
attribute (W) to an option (sticky=) would be imported at the same level 
as widgets themselves?  Is it some artifact left over from tcl, or just 
a bad idea that never went away?  Between having to explicitly reference 
every widget already (tk.Label) and having to be extra specific with 
options like sticky... I'm starting to see why everyone uses wildcard 
imports when it comes to tkinter!


Bob Greschke | 28 Feb 20:09 2014

Re: Tracebacks

On 2014-02-28, at 12:08, Bob Greschke <bob <at>> wrote:

It doesn't, this would just be more elegant, right?  It just seems funny that the interpreter doesn't help
out this one little bit more.  I'd even say why not just have a Python command that you put in your program (not
on the #! line) that tells the interpreter what to globally do with traceback error messages, especially
since these things can happen and the program just keep on running.  "set stdtraceback to file X".  For a
non-threaded/non-GUI program it might not be that big of a deal -- it hits a bug and stops -- but for a big
Tkinter program you could just keep selecting menus and buttons and never know there was a problem
somewhere.  Yes there is the logging and the traceback modules and all of that, but that's a lot of
duplication of labor.  The interpreter already knows everythin
 g, you just can't tell it what to do with the messages to make it helpful.  It seems like a small oversight to me.

On 2014-02-28, at 09:35, Cam <camfarnell <at>> wrote:

> I'm probably not understanding the question. How does what you propose differ from wrapping your whole
application in a try/except so that any uncaught exceptions result in information being written to error.txt?
> Cam
> On 14-02-28 11:33 AM, Bob Greschke wrote:
>> This isn't quite a Tkinter thing, but why can't some clever person (I couldn't do it) make it possible for
you to put something like this
>> #! /usr/bin/python -t "/home/me/error.txt",stderr
>> at the beginning of a Python program and have the interpreter direct all of the traceback messages to the
file error.txt, and stderr?  I've got a 43,000 line Tkinter/via X11 program and stupid users that won't
tell me when it crashes -- if they even notice.  Right now we create an xterm on their computer then execute
and ssh to the server where the program resides.  The errors come out in that xterm, but if the users quit they
are gone.  It seems like the interpreter would be the smartest place to put something like this since it
controls everything, and so you don't have to try and guess in which section of code you misspelled a
variable name and put it in a try-except.
>> Isn't this reasonable?  There are all kinds of questions about this problem, but never any really good
solutions.  I like this one. :)  I just wouldn't have any idea how to do it, or if it's even possible.
>> Bob
>> _______________________________________________
>> Tkinter-discuss mailing list
>> Tkinter-discuss <at>
> _______________________________________________
> Tkinter-discuss mailing list
> Tkinter-discuss <at>