TomSchimansky / CustomTkinter

A modern and customizable python UI-library based on Tkinter
MIT License
11.51k stars 1.08k forks source link

Canvas coords returns NoneType #1812

Open dpacker780 opened 1 year ago

dpacker780 commented 1 year ago

Example:

self.crop_box = [0, 0, 100, 100]
self.crop_id = self.image_view.create_rectangle(self.crop_box, outline="#fff75e", tags="cropbox")
a, b, c, d = self.image_view.coords("cropbox")

Returns an error of NoneType, when coords is used to get the values of them from the item. Coords provides both set and get functionality.

Looking at the code, it looks like with the CTkCanvas implementation it overrides and calls the super, but without any return values.

dpacker780 commented 1 year ago

A near-term fix can be simply added by placing 'return' statements in the ctk_canvas.py:

 def coords(self, tag_or_id, *args):

        if type(tag_or_id) == str and "ctk_aa_circle_font_element" in self.gettags(tag_or_id):
            coords_id = self.find_withtag(tag_or_id)[0]  # take the lowest id for the given tag
            return super().coords(coords_id, *args[:2])

            if len(args) == 3:
                super().itemconfigure(coords_id, font=("CustomTkinter_shapes_font", -int(args[2]) * 2), text=self._get_char_from_radius(args[2]))

        elif type(tag_or_id) == int and tag_or_id in self._aa_circle_canvas_ids:
            return super().coords(tag_or_id, *args[:2])

            if len(args) == 3:
                super().itemconfigure(tag_or_id, font=("CustomTkinter_shapes_font", -args[2] * 2), text=self._get_char_from_radius(args[2]))

        else:
            return super().coords(tag_or_id, *args)
ghost commented 1 year ago

Was able to replicate:

Traceback (most recent call last):
  File "/Users/dishb/Coding/test.py", line 24, in <module>
    app = App()
          ^^^^^
  File "/Users/dishb/Coding/test.py", line 11, in __init__
    self.canvas = TestCanvas(self)
                  ^^^^^^^^^^^^^^^^
  File "/Users/dishb/Coding/test.py", line 20, in __init__
    a, b, c, d = self.coords("cropbox")
    ^^^^^^^^^^
TypeError: cannot unpack non-iterable NoneType object

With the following example:

import customtkinter as ctk

class App(ctk.CTk):
    def __init__(self):

        super().__init__()

        self.grid_rowconfigure(0)
        self.grid_columnconfigure(0)

        self.canvas = TestCanvas(self)

class TestCanvas(ctk.CTkCanvas):
    def __init__(self, master):

        super().__init__(master = master)

        self.crop_box = [0, 0, 100, 100]
        self.crop_id = self.create_rectangle(self.crop_box, outline="#fff75e", tags="cropbox")
        a, b, c, d = self.coords("cropbox")
        print(a, b, c, d)

if __name__ == "__main__":
    app = App()
    app.mainloop()

On macOS 12.6.7, Python 3.11.4, and CustomTkinter 5.2.0

ghost commented 1 year ago

@dpacker780 - Create a PR?

DeltaGa commented 2 months ago

Here would be a durable fix to the issue.

    def coords(self, tag_or_id, *args):
        if type(tag_or_id) == str and "ctk_aa_circle_font_element" in self.gettags(tag_or_id):
            coords_id = self.find_withtag(tag_or_id)[0]  # take the lowest id for the given tag
            super().coords(coords_id, *args[:2])

            if len(args) == 3:
                super().itemconfigure(coords_id, font=("CustomTkinter_shapes_font", -int(args[2]) * 2), text=self._get_char_from_radius(args[2]))

        elif type(tag_or_id) == int and tag_or_id in self._aa_circle_canvas_ids:
            super().coords(tag_or_id, *args[:2])

            if len(args) == 3:
                super().itemconfigure(tag_or_id, font=("CustomTkinter_shapes_font", -args[2] * 2), text=self._get_char_from_radius(args[2]))

        else:
            coords = super().coords(tag_or_id, *args)
            if not coords:
                return [0, 0, 0, 0]  # Return default coordinates if None
            return coords