https://github.com/python/cpython/commit/fbce45b58711e9d02d270db2cd72a38dcbb345de
commit: fbce45b58711e9d02d270db2cd72a38dcbb345de
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-07-10T17:16:53Z
summary:

gh-59396: Add use_ttk parameter to tkinter ScrolledText (GH-153119)

ScrolledText gained a keyword-only use_ttk parameter to build the
surrounding frame and the vertical scroll bar from the themed
tkinter.ttk widgets instead of the classic tkinter widgets.  The
classic widgets remain the default.

Co-authored-by: Claude Opus 4.8 <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-07-05-11-36-51.gh-issue-59396.Apl7sI.rst
M Doc/library/tkinter.scrolledtext.rst
M Doc/whatsnew/3.16.rst
M Lib/test/test_tkinter/test_scrolledtext.py
M Lib/tkinter/scrolledtext.py

diff --git a/Doc/library/tkinter.scrolledtext.rst 
b/Doc/library/tkinter.scrolledtext.rst
index 30aef8748edb72..2b147873cc2349 100644
--- a/Doc/library/tkinter.scrolledtext.rst
+++ b/Doc/library/tkinter.scrolledtext.rst
@@ -23,7 +23,16 @@ most normal geometry management behavior.
 Should more specific control be necessary, the following attributes are
 available:
 
-.. class:: ScrolledText(master=None, **kw)
+.. class:: ScrolledText(master=None, *, use_ttk=False, **kw)
+
+   The keyword arguments are passed to the :class:`~tkinter.Text` widget.
+
+   When *use_ttk* is true, the surrounding frame and the scroll bar are the
+   themed :mod:`tkinter.ttk` widgets;
+   the default is the classic :mod:`tkinter` widgets.
+
+   .. versionchanged:: next
+      Added the *use_ttk* parameter.
 
 
    .. attribute:: frame
diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst
index 06c3dbb2f0f1ad..7cf1ad7ae29834 100644
--- a/Doc/whatsnew/3.16.rst
+++ b/Doc/whatsnew/3.16.rst
@@ -456,6 +456,11 @@ tkinter
   them.
   (Contributed by Serhiy Storchaka in :gh:`59396`.)
 
+* :class:`tkinter.scrolledtext.ScrolledText` gained a *use_ttk* parameter to 
use
+  the themed :mod:`tkinter.ttk` frame and scroll bar instead of the classic
+  :mod:`tkinter` widgets.
+  (Contributed by Serhiy Storchaka in :gh:`59396`.)
+
 * :class:`tkinter.font.Font` can now wrap a font description without creating a
   new named font, by passing it as *font* with ``exists=True`` and no *name*.
   This avoids a loss of precision in :meth:`~tkinter.font.Font.actual`,
diff --git a/Lib/test/test_tkinter/test_scrolledtext.py 
b/Lib/test/test_tkinter/test_scrolledtext.py
index 913e7d8aab6c46..ea4789771bb091 100644
--- a/Lib/test/test_tkinter/test_scrolledtext.py
+++ b/Lib/test/test_tkinter/test_scrolledtext.py
@@ -1,5 +1,6 @@
 import unittest
 import tkinter
+from tkinter import ttk
 from tkinter.scrolledtext import ScrolledText
 from test.support import requires
 from test.test_tkinter.support import setUpModule  # noqa: F401
@@ -19,8 +20,11 @@ def test_create(self):
         st = self.create(background='red', height=5)
         # It is a Text widget held in a Frame together with a Scrollbar.
         self.assertIsInstance(st, tkinter.Text)
+        # By default the frame and scroll bar are the classic tkinter widgets.
         self.assertIsInstance(st.frame, tkinter.Frame)
+        self.assertNotIsInstance(st.frame, ttk.Frame)
         self.assertIsInstance(st.vbar, tkinter.Scrollbar)
+        self.assertNotIsInstance(st.vbar, ttk.Scrollbar)
         self.assertEqual(st.winfo_parent(), str(st.frame))
         # str() returns the frame, so that geometry managers manage it.
         self.assertEqual(str(st), str(st.frame))
@@ -28,6 +32,12 @@ def test_create(self):
         self.assertEqual(str(st['background']), 'red')
         self.assertEqual(st['height'], 5 if self.wantobjects else '5')
 
+    def test_use_ttk(self):
+        # use_ttk=True uses the themed tkinter.ttk widgets.
+        st = self.create(use_ttk=True)
+        self.assertIsInstance(st.frame, ttk.Frame)
+        self.assertIsInstance(st.vbar, ttk.Scrollbar)
+
     def test_text_methods(self):
         st = self.create()
         st.insert('1.0', 'hello\nworld')
diff --git a/Lib/tkinter/scrolledtext.py b/Lib/tkinter/scrolledtext.py
index 8dcead5e31930e..b7b8ca1e165971 100644
--- a/Lib/tkinter/scrolledtext.py
+++ b/Lib/tkinter/scrolledtext.py
@@ -9,18 +9,25 @@
 the Scrollbar widget.
 Most methods calls are inherited from the Text widget; Pack, Grid and
 Place methods are redirected to the Frame widget however.
+
+Pass use_ttk=True for the themed tkinter.ttk frame and scroll bar
+instead of the classic tkinter widgets.
 """
 
-from tkinter import Frame, Text, Scrollbar, Pack, Grid, Place
+from tkinter import Frame, Text, Scrollbar, Pack, Grid, Place, ttk
 from tkinter.constants import RIGHT, LEFT, Y, BOTH
 
 __all__ = ['ScrolledText']
 
 
 class ScrolledText(Text):
-    def __init__(self, master=None, **kw):
-        self.frame = Frame(master)
-        self.vbar = Scrollbar(self.frame)
+    def __init__(self, master=None, *, use_ttk=False, **kw):
+        if use_ttk:
+            self.frame = ttk.Frame(master)
+            self.vbar = ttk.Scrollbar(self.frame)
+        else:
+            self.frame = Frame(master)
+            self.vbar = Scrollbar(self.frame)
         self.vbar.pack(side=RIGHT, fill=Y)
 
         kw['yscrollcommand'] = self.vbar.set
diff --git 
a/Misc/NEWS.d/next/Library/2026-07-05-11-36-51.gh-issue-59396.Apl7sI.rst 
b/Misc/NEWS.d/next/Library/2026-07-05-11-36-51.gh-issue-59396.Apl7sI.rst
new file mode 100644
index 00000000000000..d4c0473ef372e8
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-07-05-11-36-51.gh-issue-59396.Apl7sI.rst
@@ -0,0 +1,3 @@
+:class:`tkinter.scrolledtext.ScrolledText` gained a *use_ttk* parameter to use
+the themed :mod:`tkinter.ttk` frame and scroll bar instead of the classic
+:mod:`tkinter` widgets.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to