diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst index 58459017622067..a9659567eab5a7 100644 --- a/Doc/library/tkinter.rst +++ b/Doc/library/tkinter.rst @@ -3743,6 +3743,15 @@ Widget classes *yOrigin* changes by a factor of *yScale* (a factor of ``1.0`` leaves the coordinate unchanged). + .. method:: rotate(tagOrId, xOrigin, yOrigin, angle, /) + + Rotate the coordinates of all items given by *tagOrId* in canvas + coordinate space about the origin (*xOrigin*, *yOrigin*) by *angle* + degrees anticlockwise. + Negative values of *angle* rotate clockwise. + + .. versionadded:: next + .. method:: delete(*tagOrIds) Delete each of the items given by the *tagOrIds* arguments. @@ -3762,6 +3771,17 @@ Widget classes For line and polygon items *string* must be a valid sequence of coordinates. + .. method:: rchars(tagOrId, first, last, string, /) + + Replace the characters (for text items) or coordinates (for line and + polygon items) in the range from *first* to *last* inclusive of each of + the items given by *tagOrId* with *string*. + For line and polygon items *string* must be a valid sequence of + coordinates. + Items that do not support indexing ignore this operation. + + .. versionadded:: next + .. method:: itemcget(tagOrId, option) Return the current value of the configuration option *option* for the diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 692b3cfdc067b8..ec7329a3d85260 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -173,6 +173,11 @@ tkinter synchronization of the displayed view with the underlying text. (Contributed by Serhiy Storchaka in :gh:`151675`.) +* Added new :class:`!tkinter.Canvas` methods :meth:`~tkinter.Canvas.rchars` + which replaces the text or coordinates of canvas items, and + :meth:`~tkinter.Canvas.rotate` which rotates the coordinates of canvas items. + (Contributed by Serhiy Storchaka in :gh:`151876`.) + * Added a :meth:`!validate` method to the :class:`!tkinter.Entry` and :class:`!tkinter.Spinbox` widgets, which forces an evaluation of the validation command. diff --git a/Lib/test/test_tkinter/test_widgets.py b/Lib/test/test_tkinter/test_widgets.py index d0305562a0cb05..c2117981208dd5 100644 --- a/Lib/test/test_tkinter/test_widgets.py +++ b/Lib/test/test_tkinter/test_widgets.py @@ -1409,6 +1409,34 @@ def test_scale(self): self.assertRaises(TclError, c.scale, rect, 0, 0, 'spam', 2) self.assertRaises(TclError, c.scale, rect, 0, 0) # missing factors + @requires_tk(8, 6) + def test_rchars(self): + c = self.create() + # On a line item, rchars replaces a range of the coordinate list. + line = c.create_line(0, 0, 10, 10, 20, 0) + c.rchars(line, 2, 5, (30, 30, 40, 40)) + self.assertEqual(c.coords(line), [0.0, 0.0, 30.0, 30.0, 40.0, 40.0]) + # On a text item, rchars replaces a range of characters. + text = c.create_text(10, 10, text='hello') + c.rchars(text, 0, 2, 'HE') + self.assertEqual(c.itemcget(text, 'text'), 'HElo') + self.assertRaises(TclError, c.rchars) + + @requires_tk(9, 0) + def test_rotate(self): + c = self.create() + line = c.create_line(10, 0, 20, 0) + # The canvas y-axis points down, so an anticlockwise rotation about + # the origin maps (x, y) to (y, -x). + c.rotate(line, 0, 0, 90) + for got, expected in zip(c.coords(line), [0, -10, 0, -20]): + self.assertAlmostEqual(got, expected, places=3) + # A negative angle rotates clockwise, restoring the original position. + c.rotate(line, 0, 0, -90) + for got, expected in zip(c.coords(line), [10, 0, 20, 0]): + self.assertAlmostEqual(got, expected, places=3) + self.assertRaises(TclError, c.rotate, line, 0, 0, 'spam') + def test_delete(self): c = self.create() r1 = c.create_rectangle(10, 10, 30, 30) diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py index 974e386be1bb49..bf6a75875cfcb7 100644 --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -3270,6 +3270,22 @@ def tag_raise(self, *args): lift = tkraise = tag_raise # overrides Misc.tkraise + def rchars(self, *args): + """Replace the text or coordinates between indices FIRST and LAST of + the items identified by TAGORID with STRING. + + Text items replace their text; line and polygon items replace their + coordinates, in which case STRING is a list of coordinates. Other + items ignore this operation.""" + self.tk.call((self._w, 'rchars') + args) + + def rotate(self, *args): # new in Tk 9.0 + """Rotate the coordinates of the items identified by TAGORID about the + origin (XORIGIN, YORIGIN) by ANGLE degrees anticlockwise. + + Negative values of ANGLE rotate clockwise.""" + self.tk.call((self._w, 'rotate') + args) + def scale(self, *args): """Scale item TAGORID with XORIGIN, YORIGIN, XSCALE, YSCALE.""" self.tk.call((self._w, 'scale') + args) diff --git a/Misc/NEWS.d/next/Library/2026-06-22-00-55-07.gh-issue-151876.sVe0xx.rst b/Misc/NEWS.d/next/Library/2026-06-22-00-55-07.gh-issue-151876.sVe0xx.rst new file mode 100644 index 00000000000000..9dc5f2327cf415 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-22-00-55-07.gh-issue-151876.sVe0xx.rst @@ -0,0 +1,2 @@ +Add the :class:`tkinter.Canvas` methods :meth:`!rchars` and :meth:`!rotate`, +wrapping the ``rchars`` and ``rotate`` Tk canvas commands.