From f401cff30a976c56da7a74f300e2f9a0307d08ec Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 5 Jul 2026 15:11:07 +0300 Subject: [PATCH] gh-59396: Add use_ttk parameter to tkinter ScrolledText 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 --- Doc/library/tkinter.scrolledtext.rst | 11 ++++++++++- Doc/whatsnew/3.16.rst | 5 +++++ Lib/test/test_tkinter/test_scrolledtext.py | 10 ++++++++++ Lib/tkinter/scrolledtext.py | 15 +++++++++++---- .../2026-07-05-11-36-51.gh-issue-59396.Apl7sI.rst | 3 +++ 5 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-07-05-11-36-51.gh-issue-59396.Apl7sI.rst diff --git a/Doc/library/tkinter.scrolledtext.rst b/Doc/library/tkinter.scrolledtext.rst index 30aef8748edb72b..2b147873cc23493 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 8219700cc1e8385..874c97d8f49da4d 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -391,6 +391,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`.) + xml --- diff --git a/Lib/test/test_tkinter/test_scrolledtext.py b/Lib/test/test_tkinter/test_scrolledtext.py index 913e7d8aab6c46a..ea4789771bb091f 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 8dcead5e31930ea..b7b8ca1e1659717 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 000000000000000..d4c0473ef372e81 --- /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.