Python Forum
[Tkinter] Opaque letters
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] Opaque letters
#1
Hi,
I have 4 (T)Entry widgets, they are enabled or disabled in various combinations, depending on
user actions. Works fine.
I would like to add one feature, that I know exists, but is it available in tKinter?

Imagine 2 Entries state= NORMAL.
User could type anything in one or both. OK.
It would help if he knew that it is better if he typed a name in the first, and a city in the second.
(Yes I can put labels, yes he should read the manual... I would like something more sophisticated).
Sometimes you see in apps that a textbox already contains a suggested input in faint (opaque) letters,
that disappear as soon as you start typing in the box.
If he types nothing in that box, the opaque text is also not regarded as a search key.
I have looked into "transparent fonts, default text in entry boxes ... they do qualify as far as i can see.

I hope I've made myself clear.
Can I achieve this in tKinter?
thx,
Paul

Edit: it appears that something similar can be achieved by inserting a default text and bind the Entry to <FocusIn>,
deleting the default text. On pushing the search button, I will need AI to see if it's the default text, or something else was entered. :-)
Unless some standard feature comes with ttk Enries, this will do.
It is more important to do the right thing, than to do the thing right.(P.Drucker)
Better is the enemy of good. (Montesquieu) = French version for 'kiss'.
Reply
#2
Like this?
import tkinter as tk


class EnhancedEntry(tk.Entry):
    """tk.Entry widget with command callback and set method."""

    def __init__(self, *args, text="", command=None, **kwargs):
        """
        Args
        command: Function called when losing focus or enter/return pressed.
        text: Initial text placed in entry.
        """
        super().__init__(*args, **kwargs)
        self.var = tk.StringVar(self, text)
        self.configure(textvariable=self.var)
        self.command = command
        self.bind("<FocusOut>", self.accept_text)
        self.bind("<Return>", self.accept_text)

    def accept_text(self, event=None):
        """Call command when losing focus or Enter/Return pressed."""
        if self.command:
            self.command(self.get())

    def get(self):
        """Return entry text."""
        return self.var.get()

    def set(self, text):
        """Set entry text."""
        self.var.set(text)


class SuggestEntry(EnhancedEntry):
    """An Entry widget that suggests what to enter."""
    def __init__(self, *args, suggest_fg="blue", **kwargs):
        """
        Args
        suggest_fg: Color used for suggest text.
        """
        super().__init__(*args, **kwargs)
        self.suggest_fg = suggest_fg
        self.text = super().get()
        self.suggest = bool(self.text)
        self.fg = self["foreground"]
        if self.suggest:
            self.configure(foreground=self.suggest_fg)
        self.bind("<FocusIn>", self.focus_in)
        self.bind("<FocusOut>", self.focus_out)

    def focus_in(self, event=None):
        """Called when entry gets focus."""
        if self.suggest:
            self.set("")

    def focus_out(self, event=None):
        """Called when entry loses focus."""
        if self.text and not self.get():
            self.suggest = True
            self.configure(foreground=self.suggest_fg)
            super().set(self.text)
        self.accept_text()

    def get(self):
        """Return entry text.  Does not return suggested text."""
        return "" if self.suggest else super().get()

    def set(self, text):
        """Set entry text."""
        self.suggest = False
        self.configure(foreground=self.fg)
        super().set(text)


class Window(tk.Tk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        SuggestEntry(
            self, text="First Name", command=print, width=30
        ).pack(padx=10, pady=10)
        SuggestEntry(
            self, text="Last Name", command=print, width=30
        ).pack(padx=10, pady=(0, 10))


Window().mainloop()
Reply
#3
(Nov-05-2023, 03:11 PM)deanhystad Wrote: Like this?
I'm sure Montesquieu rolls in his grave.
But I must admit, it's more clever that what I came up with.
As a token of respect of your effort, I will try it, once I
found out what this super().__init__ has to do with anything.
(That's only a matter of time.)
thx,
Paul
It is more important to do the right thing, than to do the thing right.(P.Drucker)
Better is the enemy of good. (Montesquieu) = French version for 'kiss'.
Reply
#4
If you want to write GUI code you really need to learn all about classes. In my previous post I define a couple of classes to make the tkinter Entry class work the way I want it to work. I can now use these classes in every tkinter program from now on, saving me time on each. The alternative is writing ghastly code where I apply band-aids to individual entry objects. Code that is only useful for this one program.

Better is often just better.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020