1

Been playing out with tkinter until I stumble upon this. Apparently, it seems that the ttk.Entry does not recognize the configured state until the state is printed. My code is as follow:

import tkinter as tk
from tkinter import ttk

def on_focus_in(entry):

    if entry['state'] == 'disabled': #pay attention to this code block
        entry.configure(state='normal')
        entry.delete(0, 'end')
        print('1')

    print(entry_x.cget("state"))
    if entry.cget('state') == 'disabled':
        entry.configure(state='normal')
        entry.delete(0, 'end')
        print('2')

def on_focus_out(entry, placeholder):
    if entry.get() == "":
        entry.insert(0, placeholder)
        entry.configure(state='disabled')


root = tk.Tk()

entry_x = ttk.Entry(root, font=('Arial', 13), width=50)
entry_x.pack(pady=10, ipady=7)
entry_x.insert(0, "Place Holder X")
entry_x.configure(state='disabled')

entry_y = tk.Entry(root, width=50, font=('Arial', 13))
entry_y.pack(pady=10, ipady = 7)
entry_y.insert(0, "Place Holder Y")
entry_y.configure(state='disabled')

x_focus_in = entry_x.bind('<Button-1>', lambda x: on_focus_in(entry_x))
x_focus_out = entry_x.bind(
    '<FocusOut>', lambda x: on_focus_out(entry_x, 'Place Holder X'))

y_focus_in = entry_y.bind('<Button-1>', lambda x: on_focus_in(entry_y))
y_focus_out = entry_y.bind(
    '<FocusOut>', lambda x: on_focus_out(entry_y, 'Place Holder Y'))

root.mainloop()

Can anyone explain to me why is this the case?

Apparently, when I click the X entry, the log returns "2", which means that the code block that should print "1" does not run. The Y entry works fine.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • 1
    There's something strange going on with the `state` option of ttk.Entry - when it's set to one of the standard values, the value you get from `.cget()` *isn't* a string, and doesn't compare as equal to the 'normal'/'disabled' string as you'd expect. You have to apply `str()` to this object to get something that is comparable to strings - so try `if str(entry['state']) == 'disabled':`. – jasonharper Jul 13 '23 at 04:17
  • @jasonharper But why would it work after the print command, I wonder? – Đào Chí Tường Jul 13 '23 at 09:51
  • I don't see this behavior. It doesn't print `2` when I click on the entry. – Bryan Oakley Jul 14 '23 at 23:44

1 Answers1

0

The root of the problem is that entry['state'] does not return a string. Instead, it returns an object of type <class '_tkinter.Tcl_Obj'>. You're comparing it to a string, so the condition will always be false. You can cast it to the string in your if statement or use the string attribute:

if str(entry['state']) == 'disabled': 

or

if entry['state'].string == 'disabled': 
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685