diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst index 3d8983c57a12bf0..222a4d0128bd8d5 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 2b6f396bdf16dd9..aa7b9b2223ec5ec 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 0279198b179404f..93ebb4eed99a957 100644 --- a/Lib/test/test_tkinter/test_text.py +++ b/Lib/test/test_tkinter/test_text.py @@ -26,6 +26,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_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 559fe87ed46193b..8bdf7cc1e2d96b8 100644 --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -4110,6 +4110,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.