From 88e5d8a7b74e391c8ded63d3f5e9d67bf8cc2559 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 20 Jun 2026 17:11:21 +0300 Subject: [PATCH] gh-151675: Add tkinter Text.sync() and Text.pendingsync() (GH-151677) Wrap the Tk text widget "sync" and "pendingsync" subcommands, which control and report the synchronization of the displayed view with the underlying text when line heights have not yet been computed. --- Doc/library/tkinter.rst | 23 +++++++++++ Doc/whatsnew/3.16.rst | 5 +++ Lib/test/test_tkinter/test_text.py | 12 ++++++ Lib/tkinter/__init__.py | 38 +++++++++++++++++++ ...-06-19-12-00-01.gh-issue-151675.acLD7L.rst | 3 ++ 5 files changed, 81 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-06-19-12-00-01.gh-issue-151675.acLD7L.rst diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst index 3d8983c57a12..222a4d0128bd 100644 --- a/Doc/library/tkinter.rst +++ b/Doc/library/tkinter.rst @@ -5608,6 +5608,29 @@ Widget classes .. versionadded:: 3.3 + .. method:: sync(command=None) + + Control the synchronization of the displayed view with the underlying + text, which may lag behind when line heights have not yet been computed + (for example, for lines that have never been displayed). + If *command* is omitted, bring the line metrics up to date immediately by + forcing computation of any outdated line heights, and return once they + are current. + Otherwise schedule *command* to be called, with no arguments, exactly + once as soon as all line heights are up to date; if there are no pending + calculations, it is called immediately. + + .. versionadded:: next + + .. method:: pendingsync() + + Return ``True`` if the line height calculations are not up to date, and + ``False`` otherwise. + The ``<>`` virtual event fires whenever this state + changes, with the *detail* field set to the new value. + + .. versionadded:: next + .. method:: yview_pickplace(*what) Adjust the view so that the location given by *what* is visible. diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 2b6f396bdf16..aa7b9b2223ec 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -152,6 +152,11 @@ tkinter is possible. (Contributed by Serhiy Storchaka in :gh:`151674`.) +* Added new :class:`!tkinter.Text` methods :meth:`~tkinter.Text.sync` and + :meth:`~tkinter.Text.pendingsync` which control and report the + synchronization of the displayed view with the underlying text. + (Contributed by Serhiy Storchaka in :gh:`151675`.) + xml --- diff --git a/Lib/test/test_tkinter/test_text.py b/Lib/test/test_tkinter/test_text.py index 4f02502b7d21..905c194af3ac 100644 --- a/Lib/test/test_tkinter/test_text.py +++ b/Lib/test/test_tkinter/test_text.py @@ -26,6 +26,18 @@ class TextTest(AbstractTkTest, unittest.TestCase): text.debug(olddebug) self.assertEqual(text.debug(), olddebug) + def test_sync(self): + text = self.text + # sync() returns None and brings line metrics up to date. + self.assertIsNone(text.sync()) + self.assertIs(text.pendingsync(), False) + + # sync(command) schedules a one-shot callback. + events = [] + text.sync(command=lambda: events.append('synced')) + text.update() + self.assertEqual(events, ['synced']) + def test_index(self): text = self.text text.insert('1.0', 'Lorem ipsum\ndolor sit amet') diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py index 559fe87ed461..8bdf7cc1e2d9 100644 --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -4110,6 +4110,44 @@ class Text(Widget, XView, YView): the widget itself).""" return self.tk.splitlist(self.tk.call(self._w, 'peer', 'names')) + def pendingsync(self): # new in Tk 8.5 + """Return whether the line heights calculations are not up-to-date. + + Return True if the line heights calculations are not up-to-date, + and False otherwise. + """ + return self.tk.getboolean(self.tk.call(self._w, 'pendingsync')) + + def sync(self, command=None): # new in Tk 8.5 + """Control the synchronization of the view of the text widget. + + If command is not specified, immediately bring the line metrics + up-to-date by forcing computation of any outdated line heights. + The command returns immediately if there is no such outdated line. + + If command is specified, schedule it to be executed (by the event + loop) exactly once as soon as all line heights are up-to-date. + If there are no pending line metrics calculations, command is + executed immediately. + """ + if command is None: + self.tk.call(self._w, 'sync') + else: + def callit(): + try: + command() + finally: + try: + self.deletecommand(name) + except TclError: + pass + try: + callit.__name__ = command.__name__ + except AttributeError: + callit.__name__ = type(command).__name__ + name = self._register(callit) + self.tk.call(self._w, 'sync', '-command', name) + def replace(self, index1, index2, chars, *args): # new in Tk 8.5 """Replaces the range of characters between index1 and index2 with the given characters and tags specified by args. diff --git a/Misc/NEWS.d/next/Library/2026-06-19-12-00-01.gh-issue-151675.acLD7L.rst b/Misc/NEWS.d/next/Library/2026-06-19-12-00-01.gh-issue-151675.acLD7L.rst new file mode 100644 index 000000000000..92bd69de6bdc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-19-12-00-01.gh-issue-151675.acLD7L.rst @@ -0,0 +1,3 @@ +Add the :meth:`~tkinter.Text.sync` and :meth:`~tkinter.Text.pendingsync` +methods of :class:`!tkinter.Text`, wrapping the Tk ``sync`` and +``pendingsync`` subcommands. -- 2.47.3