1

I have a challenge to be done in tkinter, customtkinter and as you can see in the code I made a function that when pressing the number "0" on the keyboard the function is called and the number is printed inside the Entry, but there is a problem. The button's animation is not executed, and it would be interesting if this happens so that the code is more complete, however, I don't know how to do that.

import customtkinter as CTk
from tkinter import *
import keyboard


class MainWindow():
    def __init__(self) -> None:
        self.layout_0 = Tk()

        self.layout_1 = Frame(self.layout_0)
        self.layout_1.grid()

        self.display_0_var = StringVar()

        self.display_0 = CTk.CTkEntry(master=self.layout_1, font=('Arial', 50), 
                                      textvariable=self.display_0_var, width=294, 
                                      justify='right', corner_radius=0, border_width=0, state='readonly')
        
        self.display_0.grid(column=0, row=0)

        button = CTk.CTkButton(master=self.layout_0, command=self.input)
        button.place(x=10, y=100)

        keyboard.on_press_key('0', self.input_key)

        self.layout_0.mainloop()
    

    def input(self):
        current = self.display_0.get()
        new = current + '0'
        self.display_0_var.set(new)
        ...


    def input_key(self, events):
        self.input()
    

MainWindow()

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
DevStrom
  • 11
  • 2
  • whilst wildcard imports are allowed, for clarity it is best to avoid then: [wildcard imports](https://stackoverflow.com/questions/73698351/is-anyone-know-how-to-connect-tkinter-webcam-to-yolov5/73712541#73712541) – D.L Aug 08 '23 at 15:35
  • I don't understand why you expect button's animation if you don't click button. Normally button first runs animation and next it runs command `command=self.input` but you run directly `self.input` so it never runs button's code. It would need to send key event directly to `tkinter` - maybe it would need to use `tkinter.bind()` instead `keyboard` – furas Aug 08 '23 at 15:42
  • see source code for [customtkinter.CTkButton](https://github.com/TomSchimansky/CustomTkinter/blob/master/customtkinter/windows/widgets/ctk_button.py#L545) (and [self._image_label.bind("", self._clicked)](https://github.com/TomSchimansky/CustomTkinter/blob/master/customtkinter/windows/widgets/ctk_button.py#L269))- when you click button then it runs inner function `_clicked()` which runs animation. and maybe you should also run this `button._clicked()` instead of `self.input()` – furas Aug 08 '23 at 15:46
  • @furas Okay, do you have a practical example of this? – DevStrom Aug 08 '23 at 16:54
  • I added full working example in my answer. – furas Aug 08 '23 at 16:58
  • @furas Cool, that makes sense, but in my view when executing _clicked the animation won't stop automatically, so how would you do that? I tried a few ways but none worked. – DevStrom Aug 08 '23 at 19:50

1 Answers1

0

When user clicks CTKButton then tkinter runs inner function CTKButton._clicked() which first runs animation and later it runs function assigned by command= (in your code it will be self.input())

But when you use keyboard then you runs directly self.input() - so it doesn't runs self._clicked() and it doesn't runs animation. You should runs self._clicked() instead self.input()

    self.button = ...   # <-- use `self.`
 
    # ...

def input_key(self, events):
    #self.input()       # <-- no need it
    self.button._clicked()

You cold even reduce it to

keyboard.on_press_key('0', self.button._clicked)

And if you don't need to run it when window is hidden (and not focused) then you could use tkinter.bind() instead of keyboard

self.layout_0.bind("0", self.button._clicked)

See source code for customtkinter.CTkButton

(and self._image_label.bind("", self._clicked) and def _clicked())


EDIT:

Full working code.

import customtkinter as CTk
import tkinter as tk  # PEP8: `import *` is not preferred
#import keyboard

class MainWindow():

    def __init__(self) -> None:
        self.layout_0 = tk.Tk()

        self.layout_1 = tk.Frame(self.layout_0)
        self.layout_1.grid()

        self.display_0_var = tk.StringVar()

        self.display_0 = CTk.CTkEntry(master=self.layout_1, font=('Arial', 50), 
                                      textvariable=self.display_0_var, width=294, 
                                      justify='right', corner_radius=0, border_width=0, state='readonly')
        
        self.display_0.grid(column=0, row=0)

        self.button = CTk.CTkButton(master=self.layout_0, command=self.input)
        self.button.place(x=10, y=100)

        #keyboard.on_press_key('0', self.input_key)        # <-- old version doesn't run animation
        #keyboard.on_press_key('0', self.button._clicked)  # <-- runs animation and `self.input()`
        self.layout_0.bind("0", self.button._clicked)      # <-- runs animation and `self.input()`

        self.layout_0.mainloop()
    

    def input(self):
        current = self.display_0.get()
        new = current + '0'
        self.display_0_var.set(new)
        #...

    #def input_key(self, events):
    #    #self.input()
    #    self.button._clicked()
        

MainWindow()

PEP 8 -- Style Guide for Python Code

furas
  • 134,197
  • 12
  • 106
  • 148