GeezerVison is showing github.com — Tkinter Canvas.coords does not flatten arguments · Issue #94473 · python/cpython
Tkinter Canvas.coords does not flatten arguments #94473DescriptionBug report
Double nested arrays in tk.coords will produce errors in tkinter (_tkinter.TclError: wrong # coordinates: expected at least 4, got 2 in this case)
import tkinter as tk
coords = [[100, 100], [300, 300]]
root = tk.Tk()
canvas = tk.Canvas(width=400,
height=400,
background="bisque")
canvas.pack(fill="both", expand=True)
line = canvas.create_line(coords)
coords[1] = [200, 200]
canvas.coords(line, coords) # line with error
root.mainloop()
Your environment
- CPython versions tested on: 3.10.4
- Operating system: Windows 10
Linked PRs
ActivityWhy-not-now commented on Jul 1, 2022 Upon further inspection, it seems that canvas.coords do not allow doubly nested loops stevendaprano commented on Jul 1, 2022 Is there something that suggests to you that using a numpy array for coords ought to work?
I don't know what you mean by double nested loops. There's no loop here. Why-not-now commented on Jul 1, 2022 Because the numpy array is similar to a list, and lists works for canvas.create_line() etc.
Also doubly nested would be a list inside a list. So canvas.coords(line, [[100, 100], [300, 300]]) wouldn't work while canvas.create_line([[100, 100], [300, 300]]) would work Why-not-now commented on Jul 1, 2022 Example of this is
import numpy as np
import tkinter as tk
root = tk.Tk()
canvas = tk.Canvas(width=400,
height=400,
background="bisque")
canvas.pack(fill="both", expand=True)
line = canvas.create_line([[100, 100], [300, 300]])
canvas.coords(line, [[100, 100], [200, 200]]) # line with error
root.mainloop()```ronaldoussoren commented on Jul 1, 2022 As mentioned on discuss.python.org the coords method requires at least 4 coordinates, not 2. The error message states this:
_tkinter.TclError: wrong # coordinates: expected at least 4, got 2
Supporting numpy arrays for coordinates, or rather anything other than builtin lists and tuples, could be a feature request, but would require a clear use case that sells this change. Why-not-now commented on Jul 1, 2022 I see, thanks for the help. Just one more question before I close this issue, why does canvas.coords(line, [[100, 100], [200, 200]]) not represent 4 coordinates while canvas.create_line([[100, 100], [300, 300]]) does? ronaldoussoren commented on Jul 2, 2022 Good question. To be honest I'm not a Tkinter expert.
Looking at the implementation and Tk documentation:
- The Tk implementation represents the various x, y coordinates as separate arguments (see https://www.tcl.tk/man/tcl8.0/TkCmd/canvas.html#M40)
- The Python wrapper for the create_* methods flattens arguments, basically turning
canvas.create_line((startX, startY), (stopX, stopY)) into canvas.create_line(startX, startY, stopX, stopY)
- The Python wrapper for coord method does not flatten, which means you have to pass the various coordinates as separate arguments (
canvas.coords(line, startX, startY, stopX, stopY))
I don't know if that's intentional, but is does feel inconsistent. That said, canvas.coords(line) will return the current coordinates of the line (or other object) as an flattened list as well. Changing that is not backward compatible and IMHO is not worth changing even if we'd add argument flattening to the coords wrapper.
If you don't mind I'll change to title of this issue to Tkinter Canvas.coords does not flatten arguments, and leave it open for someone that knows more about Tk to comment on whether or not this is intentional behaviour. changed the title [-]Numpy array not compatible with tkinter[/-] [+]Inconsistent results for canvas.coords and canvas.create_<widget>[/+] on Jul 2, 2022changed the title [-]Inconsistent results for canvas.coords and canvas.create_<widget>[/-] [+]Tkinter Canvas.coords does not flatten arguments[/+] on Jul 2, 2022Why-not-now commented on Jul 3, 2022 Looking through the source code, at line 2817 of tkinter/__init__.py,
def coords(self, *args):
"""Return a list of coordinates for the item given in ARGS."""
# XXX Should use _flatten on args
return [self.tk.getdouble(x) for x in
self.tk.splitlist(
self.tk.call((self._w, 'coords') + args))]
there is one comment saying they should use _flatten on args. Reacted by Akuli, Benedek Dévényi, Serhiy Storchaka and Why-not-now serhiy-storchaka commented on Oct 14, 2022 It would be a new feature. And I agree that it is worth to use _flatten on args. Tk canvas subcommands coord and create has the same signature for coordinates. It natively supports both canvas.coords(line, 100, 100, 200, 200) and canvas.coords(line, [100, 100, 200, 200]), but unfortunately not more natural in Python canvas.coords(line, [100, 100], [200, 200]) and canvas.coords(line, [[100, 100], [200, 200]]).
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|