From 487ae5be26df7d2ec7fdb0007a8d43dd1e52d8e4 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 19 Jun 2026 00:20:00 +0300 Subject: [PATCH] gh-151675: Add tkinter Text.sync() and Text.pendingsync() 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 | 8 ++++ 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, 84 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 b0421721bf8d7e5..2be71e4a1fbb3a3 100644 --- a/Doc/library/tkinter.rst +++ b/Doc/library/tkinter.rst @@ -5594,6 +5594,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 8e4c4a1e9b1de02..fb112b68a74dcd4 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -138,6 +138,14 @@ shlex a string, even if it is already safe for a shell without being quoted. (Contributed by Jay Berry in :gh:`148846`.) +tkinter +------- + +* 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 453a4505a0a4da8..31c297bdd948864 100644 --- a/Lib/test/test_tkinter/test_text.py +++ b/Lib/test/test_tkinter/test_text.py @@ -25,6 +25,18 @@ def test_debug(self): 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_search(self): text = self.text diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py index ba8365f56c37a70..584cebfb22bd3c6 100644 --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -4094,6 +4094,44 @@ def peer_names(self): # new in Tk 8.5 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 000000000000000..92bd69de6bdc0ec --- /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.