Skip to content

'cget' returns '_tkinter.Tcl_Obj' instead of 'str' when called on a class widget inheriting from ttk #98815

Closed as not planned
@JRiggles

Description

@JRiggles

Bug report

Calling cget on a widget typically returns a str value, but when called on a custom widget class that inherits from ttk, cget returns _tkinter.Tcl_Obj instead. This issue was demonstrated in this StackOverflow Question, where it was suggested that I submit this bug report.

EXAMPLE:

import tkinter as tk
from tkinter import ttk
# some tkinter boilerplate (i.e. 'root = tk.Tk()') has been left out for brevity

# tk Entry widget
tk_entry = tk.Entry()
print(type(tk_entry.cget('fg')))
# => <class 'str'>

# ttk Entry widget
ttk_entry = ttk.Entry()
print(type(ttk_entry.cget('foreground')))
# => <class 'str'>

# subclassed ttk Entry widget
ph_entry = PlaceholderEntry()
print(type(ph_entry.cget('foreground')))
# => <class '_tkinter.Tcl_Obj'> ... Why is this different?

# ultra basic subclass widget
basic_entry = BasicEntry()
print(type(basic_entry.cget('foreground')))
# => <class 'str'>


# demo class inheriting from ttk.Entry (as shown on StackOverflow)
class PlaceholderEntry(ttk.Entry):
    """Entry widget with focus-toggled placeholder text"""
    def __init__(
        self, parent, placeholder='', color='#828790', *args, **kwargs
    ):
        super().__init__(parent, *args, **kwargs)
        self.placeholder = placeholder
        self._ph_color = color
        self._default_fg = self.cget('foreground')  # default foreground color
        # focus bindings
        self.bind('<FocusOut>', self.set_placeholder)
        self.bind('<FocusIn>', self.clear_placeholder)
        # initialize placeholder
        self.set_placeholder()

    def set_placeholder(self, *args):  # on focus out
        if not self.get():  # if the entry has no text...
            self.insert(0, self.placeholder)
            self.configure(foreground=self._ph_color)

    def clear_placeholder(self, *args): # on focus in
        if str(self.cget('foreground')) == self._ph_color:  # str() is used here to make this work as intended
            self.delete(0, tk.END)
            self.configure(foreground=self._default_fg)


# minimal demo class inheriting from ttk.Entry that *doesn't* have this issue
class BasicEntry(ttk.Entry):
    def __init__(self, parent):
        super().__init__(parent)

Your environment

  • Running code directly from VSCode
  • CPython versions tested on: 3.11.0, 64-bit
  • Operating system and architecture: Windows 10

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions