Skip to content

Commit 9efc337

Browse files
Add ScrollableFrame
1 parent 521b6f1 commit 9efc337

3 files changed

Lines changed: 87 additions & 13 deletions

File tree

tk_tools/__init__.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
1-
from tk_tools.canvas import RotaryScale, Gauge, Graph, Led
2-
from tk_tools.groups import EntryGrid, LabelGrid, \
3-
KeyValueEntry, ButtonGrid, Calendar, MultiSlotFrame, \
4-
SevenSegment, SevenSegmentDigits
5-
from tk_tools.widgets import SmartOptionMenu, SmartSpinBox, \
6-
SmartCheckbutton, SmartListBox, BinaryLabel, ByteLabel
1+
from tk_tools.canvas import Gauge, Graph, Led, RotaryScale
2+
3+
from tk_tools.groups import ButtonGrid, Calendar, EntryGrid, KeyValueEntry, LabelGrid, \
4+
MultiSlotFrame, SevenSegment, SevenSegmentDigits
5+
6+
from tk_tools.widgets import BinaryLabel, ByteLabel, ScrollableFrame, SmartCheckbutton, SmartListBox, SmartOptionMenu, SmartSpinBox
7+
78
from tk_tools.tooltips import ToolTip
89

910
from tk_tools.version import __version__
1011

1112

1213
__all__ = [
13-
'RotaryScale', 'Gauge', 'Graph', 'Led',
14-
'EntryGrid', 'LabelGrid', 'ButtonGrid', 'KeyValueEntry',
15-
'SmartOptionMenu', 'SmartSpinBox', 'SmartCheckbutton',
16-
'SmartListBox', 'Calendar', 'MultiSlotFrame',
14+
'BinaryLabel', 'ButtonGrid', 'Calendar',
15+
'ByteLabel', 'EntryGrid', 'Gauge', 'Graph', 'KeyValueEntry', 'LabelGrid', 'Led',
16+
'MultiSlotFrame',
17+
'RotaryScale', 'ScrollableFrame',
18+
'SmartCheckbutton', 'SmartListBox', 'SmartOptionMenu', 'SmartSpinBox',
1719
'SevenSegment', 'SevenSegmentDigits',
18-
'BinaryLabel', 'ByteLabel', 'ToolTip',
20+
'ToolTip',
1921
'__version__'
2022
]

tk_tools/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '0.15.0'
1+
__version__ = '0.16.0'

tk_tools/widgets.py

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import logging
22
import tkinter as tk
33
import tkinter.ttk as ttk
4-
from typing import List
4+
from typing import List, Union
55

66

77
logger = logging.getLogger(__name__)
@@ -459,3 +459,75 @@ class ByteLabel(BinaryLabel):
459459
Still here for backwards compatibility.
460460
"""
461461
pass
462+
463+
464+
class ScrollableFrame(ttk.Frame):
465+
"""
466+
Add scrollable frame which will automatically adjust to the contents. Note that widgets must be packed or \
467+
gridded on the ``scrollable_frame`` widget contained within the object.
468+
469+
Example:
470+
471+
root = tk.Tk()
472+
473+
sf = ScrollableFrame(root)
474+
sf.pack()
475+
476+
# add a long list of widgets
477+
def add_widget(i):
478+
tk.Label(sf.scrollable_frame, # <--- note that widgets are being added to the scrollable_frame!
479+
text=f'label {i}').grid(sticky='w')
480+
481+
for i in range(40):
482+
sf.after(i*100, lambda i=i: add_widget(i))
483+
484+
root.mainloop()
485+
486+
:param master: the master widget
487+
:param height: an integer specifying the height in pixels
488+
:param args: the arguments to pass along to the frame
489+
:param kwargs: the arguments/options to pass along to the frame
490+
"""
491+
def __init__(self, master: Union[tk.Frame, ttk.Frame, tk.Toplevel, tk.Tk],
492+
height: int = 400, *args, **kwargs):
493+
super().__init__(master, *args, **kwargs)
494+
self._parent = master
495+
496+
self._canvas = tk.Canvas(self, height=height)
497+
scrollbar = ttk.Scrollbar(self, orient="vertical", command=self._canvas.yview)
498+
self.scrollable_frame = ttk.Frame(self._canvas)
499+
500+
self.scrollable_frame.bind(
501+
"<Configure>",
502+
lambda e: self._canvas.configure(
503+
scrollregion=self._canvas.bbox("all"),
504+
width=e.width
505+
)
506+
)
507+
508+
self._canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
509+
510+
self._canvas.configure(yscrollcommand=scrollbar.set)
511+
512+
self._canvas.pack(side="left", fill="both", expand=True)
513+
scrollbar.pack(side="right", fill="y")
514+
515+
self._canvas.bind_all("<MouseWheel>", self._on_mousewheel)
516+
517+
def _on_mousewheel(self, event):
518+
self._canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
519+
520+
521+
if __name__ == '__main__':
522+
root = tk.Tk()
523+
524+
sf = ScrollableFrame(root)
525+
sf.pack()
526+
527+
def add_widget(i):
528+
tk.Label(sf.scrollable_frame, text=f'label {i}').grid(sticky='w')
529+
530+
for i in range(40):
531+
sf.after(i*100, lambda i=i: add_widget(i))
532+
533+
root.mainloop()

0 commit comments

Comments
 (0)