Change OnScreen Keyboard StringVar (Show linked to one Entry)

Peter Otten __peter__ at web.de
Sun Apr 10 09:18:06 EDT 2016


Diego Lelis wrote:

> Hi guys, im having a little problem to make the StringVar Linked to my
> OnScreen Keyboard Change when the user click in one Entry.
> 
> Here's my code:
> from tkinter import *
> 
> ____________________________Begin
> Code_______________________________________
> 
> def frame(root, side):
>     w = Frame(root)
>     w.pack(side=side, expand=YES, fill=BOTH)
>     return w
> 
> def button(root, side, text, command=None):
>     w = Button(root, text=text, command=command)
>     w.pack(side=side, expand=YES, fill=BOTH)
>     return w
> 
> 
> class Keyboard(Frame):
>     def __init__(self):
>         Frame.__init__(self)
>         self.option_add('*Font', 'Verdana 12 bold')
>         self.pack(expand=YES, fill=BOTH)
>         self.master.title('Simple Screen Keyboard')
> 
>         def detect_Focus(event):
>             print ('Change selected_display to the display correspondent
>             to selected entry')
> 
>         display_1 = StringVar()
>         entry_1 = Entry(self, relief=SUNKEN, textvariable=display_1)
>         entry_1.bind('<FocusIn>', detect_Focus)
>         entry_1.pack(side=TOP, expand=YES, fill=BOTH)
> 
> 
>         display_2 = StringVar()
>         entry_2 = Entry(self, relief=SUNKEN, textvariable=display_2)
>         entry_2.bind('<FocusIn>', detect_Focus)
>         entry_2.pack(side=TOP, expand=YES, fill=BOTH)
> 
>         selected_display = display_1
> 
>         for key in ("123", "456", "789", "-0."):
>             keyF = frame(self, TOP)
>             for char in key:
>                 button(keyF, LEFT, char,
>                        lambda w=selected_display, c=char: w.set(w.get() +
>                        c))
> 
> if __name__ == '__main__':
>     Keyboard().mainloop()
> 
> 
> ____________________________End
> Code_______________________________________
> 
> 
> When i run the detect_Focus Function, i wanted change the
> selected_display, to make the user change the entry2(display_2), using my
> on screen keyboard.

The problem is that by setting the default for w

>                 button(keyF, LEFT, char,
>                        lambda w=selected_display, c=char: w.set(w.get() +
>                        c))

you bind w to the current selected display, and to change that binding 
afterwards is messy. Instead you should use a variable in a scope shared by 
detect_Focus() and the lambda. If there is only ever one instance of 
Keyboard this could be the global scope, but using a function or a helper 
class if better. Here's the lazy approach that uses the scope of the 
__init__() method:

class Keyboard(Frame):
    def __init__(self):
        Frame.__init__(self)
        self.option_add('*Font', 'Verdana 12 bold')
        self.pack(expand=YES, fill=BOTH)
        self.master.title('Simple Screen Keyboard')

        def detect_Focus(event):
            nonlocal display
            print ('Change selected_display to the display correspondent to 
selected entry')
            display = display_2 if display is display_1 else display_1

        display_1 = StringVar()
        entry_1 = Entry(self, relief=SUNKEN, textvariable=display_1)
        entry_1.bind('<FocusIn>', detect_Focus)
        entry_1.pack(side=TOP, expand=YES, fill=BOTH)


        display_2 = StringVar()
        entry_2 = Entry(self, relief=SUNKEN, textvariable=display_2)
        entry_2.bind('<FocusIn>', detect_Focus)
        entry_2.pack(side=TOP, expand=YES, fill=BOTH)

        display = display_1

        for key in ("123", "456", "789", "-0."):
            keyF = frame(self, TOP)
            for char in key:
                button(keyF, LEFT, char,
                       lambda c=char: display.set(display.get() + c))





More information about the Python-list mailing list