Search code examples
pythontkinterkeyboardinterrupt

tkinter keyboard interrupt isn't handled until tkinter frame is raised


I have a GUI application written with python+tkinter. In my workflow, I generally start the gui from the commandline, do some things in the gui and then I find myself navigating to other terminal windows to do some work. Inevitably, I want to shut down the GUI at some point, and out of habit I often just navigate to the terminal that started the GUI and send a KeyboardInterrupt (Ctrl-c). However, This interrupt is not recieved until I raise the GUI window in the Window manager. Does anyone know why this happens? If the gui is started in a single function, is there a simple workaround -- multiprocessing maybe?


Solution

  • from the newsgroups:

    I'm using Python 1.5 under Redhat Linux 5.0. I'm trying to figure out the best way to trap a SIGINT (or Ctrl-C) when using tkinter. To illustrate the problem I have, do the following ...

    -- Build Python-1.5 with tkinter enabled.

    -- Go into the Demo/tkinter/guido directory under the Python-1.5 build tree.

    -- Type "python imageview.py image-file", where "image-file" is the full pathname of a displayable image.

    -- Once the image pops up, make sure that the window focus is held by the xterm window from which the "python ..." command was just now invoked.

    -- Hit Ctrl-C.

    At this point, nothing happens. The Ctrl-C seems to be ignored. But now ...

    -- Without hitting any more keys on the keyboard, set the window focus to the displayed image window.

    As soon as that window gets the focus, the Ctrl-C takes effect.

    My question is this: is there any way to restructure the "imageview.py" program so that it will respond to SIGINT (Ctrl-C) immediately, without having to set the window focus to the displayed image first?

    Thanks in advance for any help you folks can give me.
    ---- What you're seeing is caused by the way signal handlers are handled. You're stuck in the Tcl/Tk main loop, and signal handlers are only handled by the Python interpreter. A quick workaround is to use after() to schedule a dummy function to be called once a second or so -- this will make it appear that your signal is handled in a timely manner.

    --Guido van Rossum