Akascape / CTkToolTip

Small pop-up widget for displaying details inside customtkinter. (extension/add-on)
Creative Commons Zero v1.0 Universal
111 stars 7 forks source link

CTkToolTip breaks Python dunder methods #6

Closed avalon60 closed 1 year ago

avalon60 commented 1 year ago

Hi @Akascape.

There is an issue with CTKToolTip, wherein if you define override the builtin dunder methods, for example the __str__ method, of a class, then CTkoolTip causes an exception:

This code demonstrates the issue:

import customtkinter
from lib.ctk_tooltip.ctk_tooltip import CTkToolTip
class ToplevelWindow(customtkinter.CTkToplevel):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        attrs = vars(self)
        # print(f'Attrs = {attrs}')
        self.geometry("400x300")

        self.label = customtkinter.CTkLabel(self, text="ToplevelWindow")
        self.label.pack(padx=20, pady=20)
        print(f'Master: {self.master}')

class App(customtkinter.CTk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.geometry("500x400")

        self.button_1 = customtkinter.CTkButton(self, text="open toplevel", command=self.open_toplevel)
        self.button_1.pack(side="top", padx=20, pady=20)
        button_tooltip = CTkToolTip(master=self.button_1, message='Hello world')

        self.toplevel_window = None

    def __str__(self):
        return 'MainWindow'

    def open_toplevel(self):
        if self.toplevel_window is None or not self.toplevel_window.winfo_exists():
            self.toplevel_window = ToplevelWindow(self)  # create window if its None or destroyed
        else:
            self.toplevel_window.focus()  # if window exists focus it

app = App()
app.mainloop()

This causes the exception:

File "/home/clive/.config/JetBrains/PyCharmCE2023.1/scratches/scratch.py", line 38, in <module>
    app = App()
  File "/home/clive/.config/JetBrains/PyCharmCE2023.1/scratches/scratch.py", line 23, in __init__
    button_tooltip = CTkToolTip(master=self, message='Hello world')
  File "/home/clive/PycharmProjects/ctk_theme_builder/lib/ctk_tooltip/ctk_tooltip.py", line 52, in __init__
    self.transient(self.master)
  File "/usr/lib/python3.10/tkinter/__init__.py", line 2262, in wm_transient
    return self.tk.call('wm', 'transient', self._w, master)
_tkinter.TclError: bad window path name "MainWindow"

If I comment the tool-tip out, the program runs without error and when the button is pressed, the print statement works as expected, as we see here:

image

Akascape commented 1 year ago

@avalon60 button_tooltip = CTkToolTip(widget=self.button_1, message='Hello world') it was widget not master.

avalon60 commented 1 year ago

@avalon60 button_tooltip = CTkToolTip(widget=self.button_1, message='Hello world') it was widget not master.

Thanks, but I tried that and it's the same result: image

Akascape commented 1 year ago

@avalon60 I am not getting this error on windows. I know what's causing the issue.

Akascape commented 1 year ago

@avalon60 Try removing this line having self.transient: https://github.com/Akascape/CTkToolTip/blob/d8e64cf922088e21f94e3fb083aac5eada8f98da/CTkToolTip/ctk_tooltip.py#L51

avalon60 commented 1 year ago

@Akascape I am on Linux Mint. Commenting out the transient line does fix the problem, thanks. Not sure whether this is relevant, but out of interest, when I hover over the line in Pycharm, I get this:

Unexpected type(s): (Misc) Possible type(s): (None) (Wm | Tcl_Obj | Tcl_Obj) 
 Inspection info:
Reports type errors in function call expressions, targets, and return values. In a dynamically typed language, this is possible in a limited number of cases.
Types of function parameters can be specified in docstrings or in Python 3 function annotations.
Example:
def foo() -> int:
    return "abc" # Expected int, got str

a: str
a = foo() # Expected str, got int
With the quick-fix, you can modify the problematic types:
def foo() -> str:
    return "abc"

a: str
a = foo()
avalon60 commented 1 year ago

Closed