1

There seems to be a keyboard input problem with Zelle Graphics when using multiple windows. Mouse operations work fine but not keyboard operations.

It seems that when the 2nd window is opened, keyboard input from the 1st window goes to the object associated with the 2nd window. And then if you close the 2nd window, you have lost all keyboard input.

In the test below window 1's input is printed as each key is received. When a w is hit the 2nd window opens. Typing in window 2 appears on the console. But then highlighting window 1, any characters entered is coming in as characters from window 2, and the console display 'window 2: and the character', appears. So keyboard input on window 1 stops when window 2 comes up. Window 1's checkKey just keeps returning a zero-length string showing no input received. When a c is entered window 2 closes and no keyboard input works from then on. Window 1 no longer receives characters.

This has been tried on two different windows 7 computers under version 3.6 of Python.

Mouse operations work correctly, providing mouse input to the correct window object, but not keyboard input.

Is anyone aware of a fix or a way around this?

from graphics import *

# open window 1
win = GraphWin("window 1",500,500)
win2open = False

while True:
    k = win.checkKey()
    if k != '':
        # display input from window 1
        print ("window 1: ",k)
    if k == 'w':
        # if a 'w' is pressed open window 2 
        win2 = GraphWin("window 2",250,250) 
        win2open = True 
    if win2open == True:    
        m = win2.checkKey()
        if m != '':
          # if windows 2 is open print chars from window 2
            print ('window 2',m)
        if (m == 'c'):
            # if 'c' enterred on window 2 close window 
            win2.close()
            win2open = False
Jay Mosk
  • 197
  • 1
  • 2
  • 8
  • I tried it with 3 windows and the input always comes through the last window created regardless of which window you highlight and use for input. I closed window 2 of 3 and it has no effect. Input is coming via the checkKey function of the last window opened instead of through the window object checking for input from each particular window. – Jay Mosk Jun 19 '22 at 20:05
  • Every time you create a `GraphWin`, all keyboard events for the entire application are bound to a keyboard event handler method defined by the class to that instance. If more than one exists at the same time the last one created will be the one receiving those keyboard events. The Zelle `graphics` module does not have anything to undo or redirect this that is documented (or that I can find). – martineau Jun 19 '22 at 20:08
  • How would you like keyboard input to work when there are multiple `GraphWin`s? In other words what would "work correctly" be in that situation? Also note that the fact that this issue is holding up your product release isn't especially [relevant](https://meta.stackoverflow.com/questions/326569/under-what-circumstances-may-i-add-urgent-or-other-similar-phrases-to-my-quest). – martineau Jun 19 '22 at 20:20
  • I would expect the keyboard input would be directed to the window that is active. Each window has input fields to fill out. Different data types on each window. I would expect the user to be able to fill out data on each of the open windows. The mouse function and keyboard functions should work the same way. There is now problem using the mouse in each window and selecting buttons on either window and reacting to them. The keyboard should act the same way. – Jay Mosk Jun 19 '22 at 21:05
  • So I guess the only way around this would be to keep the 2nd window open and determine where to place data based on the last mouse input. But then if the 2nd window is closed, the program is useless as keyboard input is lost. So the 'fix" would require modifying the Zelle graphic code to tie the event handler to each window object and not to the one created last. Is the Zelle graphics code available in source form or is it imported in some pre-compiled format? Wish there was a better way around this. – Jay Mosk Jun 19 '22 at 21:15
  • It's the `self.bind_all()` that's causing your problem. It binds **all** keyboard events in your application to the `_onKey()` method of *that* `GraphWin` instance and it stays that way until another ``GraphWin` is created, in which case they're all sent to that one, etc. – martineau Jun 19 '22 at 21:55
  • I tried changing the self.bind_all() to self.bind() just as it is for mouse events, but then no keyboard input was received at all. – Jay Mosk Jun 19 '22 at 22:09
  • It's not as simple changing the `bind_all()`. You're going to need further modifications which will require understanding `tkinter` to some degree. – martineau Jun 19 '22 at 22:41
  • What is fascinating is that I created a Tkinter app that opens 3 windows and gets keyboard input from each and mouse positions and reports the window it comes from. It works perfectly fine. It binds both the keyboard and the left mouse click. So the issue appears to be in the way graphics.py is set up . Yes bind_all sends all keyboard input to the last open window and I confirmed that with the Tkinter test. But changing bind_all to bind in graphics.py causes no keyboard input to be detected while using the two bind commands in the Tkinter test works just fine. Need to delve further. – Jay Mosk Jun 23 '22 at 12:34
  • I resolved the problem and now keyboard input arrives via the window object associated with the window that is active when the characters arrive. It was the way graphics.py was calling tkinter. The solution is to update graphics.py and change self.bind_all('', self._onKey) to master.bind('', self._onKey). Not sure why it works as coded for mouse clicks, but for keyboard input the events need to come through master which is equal to the Toplevel window in use at the time the window object is created. – Jay Mosk Jun 23 '22 at 19:55
  • That sounds like a simple solution if that's all you needed. I was having some success with something that didn't require changing `graphics.py`, but consequently was somewhat hacky given the restriction. – martineau Jun 23 '22 at 20:06
  • I would think this update would be of interest to others. But I don't know if it should just be made part of what is downloaded from pip or if there is some process for some level of field use before updating the master release stored there. Where can one find information regarding the manner to update software distributed via pip? – Jay Mosk Jun 23 '22 at 20:18
  • The pip package was not created by [John M. Zelle](https://mcsp.wartburg.edu/zelle/), the author of the software, which he released under the terms of the [GPL](http://www.gnu.org/licenses/gpl.html) — so you can pretty much do what you want as long as you follow its terms. You can contact the pip package maintainer Patrick Narkinsky at patrick@narkinsky.com and ask about making changing to the pypi version. – martineau Jun 23 '22 at 20:40
  • Since I have not tested this update with the "Entry" input type fields of graphics.py, I am not going to release this update for pip distribution. If tested in the future, the version 6 of graphics can be released with this update. – Jay Mosk Jun 24 '22 at 11:07
  • I contacted John Zelle and he suggested to change self.bind_all('', self._onKey) to self.master.bind('', self._onKey). although my use of master.bind() also worked. – Jay Mosk Jul 11 '22 at 17:00

0 Answers0