1"""A ScrolledText widget feels like a text widget but also has a 2vertical scroll bar on its right. (Later, options may be added to 3add a horizontal bar as well, to make the bars disappear 4automatically when not needed, to move them to the other side of the 5window, etc.) 6 7Configuration options are passed to the Text widget. 8A Frame widget is inserted between the master and the text, to hold 9the Scrollbar widget. 10Most methods calls are inherited from the Text widget; Pack, Grid and 11Place methods are redirected to the Frame widget however. 12""" 13 14from tkinter import Frame, Text, Scrollbar, Pack, Grid, Place 15from tkinter.constants import RIGHT, LEFT, Y, BOTH 16 17__all__ = ['ScrolledText'] 18 19 20class ScrolledText(Text): 21 def __init__(self, master=None, **kw): 22 self.frame = Frame(master) 23 self.vbar = Scrollbar(self.frame) 24 self.vbar.pack(side=RIGHT, fill=Y) 25 26 kw.update({'yscrollcommand': self.vbar.set}) 27 Text.__init__(self, self.frame, **kw) 28 self.pack(side=LEFT, fill=BOTH, expand=True) 29 self.vbar['command'] = self.yview 30 31 # Copy geometry methods of self.frame without overriding Text 32 # methods -- hack! 33 text_meths = vars(Text).keys() 34 methods = vars(Pack).keys() | vars(Grid).keys() | vars(Place).keys() 35 methods = methods.difference(text_meths) 36 37 for m in methods: 38 if m[0] != '_' and m != 'config' and m != 'configure': 39 setattr(self, m, getattr(self.frame, m)) 40 41 def __str__(self): 42 return str(self.frame) 43 44 45def example(): 46 from tkinter.constants import END 47 48 stext = ScrolledText(bg='white', height=10) 49 stext.insert(END, __doc__) 50 stext.pack(fill=BOTH, side=LEFT, expand=True) 51 stext.focus_set() 52 stext.mainloop() 53 54 55if __name__ == "__main__": 56 example() 57