]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-151675: Add tkinter Text.sync() and Text.pendingsync() (GH-151677)
authorSerhiy Storchaka <storchaka@gmail.com>
Sat, 20 Jun 2026 14:11:21 +0000 (17:11 +0300)
committerGitHub <noreply@github.com>
Sat, 20 Jun 2026 14:11:21 +0000 (17:11 +0300)
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
Doc/whatsnew/3.16.rst
Lib/test/test_tkinter/test_text.py
Lib/tkinter/__init__.py
Misc/NEWS.d/next/Library/2026-06-19-12-00-01.gh-issue-151675.acLD7L.rst [new file with mode: 0644]

index 3d8983c57a12bf03e53f38319b0d691f0d2bf2ff..222a4d0128bd8d5ea7868ca445472792b2b4d238 100644 (file)
@@ -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 ``<<WidgetViewSync>>`` 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.
index 2b6f396bdf16dd9376d9800b0c40d36dcbc1ba8d..aa7b9b2223ec5ec35c2cf291607279729bb4e0f9 100644 (file)
@@ -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
 ---
 
index 4f02502b7d216a1e7b4140715fd6e24e4486fb98..905c194af3ac4741bbb3701226ea31f153e078fc 100644 (file)
@@ -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')
index 559fe87ed46193b1dbe10cb801145040f3352cf4..8bdf7cc1e2d96b8dfc01f364d254f292e5beefe3 100644 (file)
@@ -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 (file)
index 0000000..92bd69d
--- /dev/null
@@ -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.