Как закодировать модуль tkinter "scrolledtext"

В приведенном ниже коде приведен уродливый, но функциональный пример использования полосы прокрутки в текстовом виджете и возникает несколько вопросов. Примечание: это делается с помощью Python 3 в окне окна.

  • Полоса прокрутки, которая появляется, прикреплена к кадру, и хотя она прокручивает содержимое текстового поля, я бы предпочел, чтобы она была прикреплена к самому текстовому виджету. Я не смог добиться этого.

  • Существует ряд ссылок на модуль Tkinter под названием "scrolledtext", который должен быть гораздо лучшим механизмом для добавления полос прокрутки в текстовые поля, но я не нашел примеров того, как его импортировать и вызывать это то, что я могу работать (возможно, нужен пример).


frame1 = tk.Frame(win,width=80, height=80,bg = '#808000')
frame1.pack(fill='both', expand='yes')
scrollbar = Scrollbar(frame1) 
scrollbar.pack(side=RIGHT, fill=Y)
editArea = Text(frame1, width=10, height=10, wrap=WORD, yscrollcommand=scrollbar.set)
editArea.pack()    
scrollbar.config(command=editArea.yview)
editArea.place(x=10,y=30)

Ответ 1

Вы были правы, вы можете использовать виджет ScrolledText из модуля tkinter.scrolledtext, например:

import tkinter as tk
import tkinter.scrolledtext as tkst

win = tk.Tk()
frame1 = tk.Frame(
    master = win,
    bg = '#808000'
)
frame1.pack(fill='both', expand='yes')
editArea = tkst.ScrolledText(
    master = frame1,
    wrap   = tk.WORD,
    width  = 20,
    height = 10
)
# Don't use widget.place(), use pack or grid instead, since
# They behave better on scaling the window -- and you don't
# have to calculate it manually!
editArea.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
# Adding some text, to see if scroll is working as we expect it
editArea.insert(tk.INSERT,
"""\
Integer posuere erat a ante venenatis dapibus.
Posuere velit aliquet.
Aenean eu leo quam. Pellentesque ornare sem.
Lacinia quam venenatis vestibulum.
Nulla vitae elit libero, a pharetra augue.
Cum sociis natoque penatibus et magnis dis.
Parturient montes, nascetur ridiculus mus.
""")
win.mainloop()

И вот вы:

enter image description here

Ответ 2

Во время использования виджета ScrolledText вы можете сэкономить несколько строк кода, но он не сделает ничего, что вы не можете сделать сами. Выполнение этого самостоятельно поможет устранить некоторые из тайн.

Ты на самом деле делаешь все почти правильно. Ошибка, которую вы делаете, заключается в том, что ваш текстовый виджет полностью заполняет контейнер, а не просто его крошечную часть.

Стандартный способ сделать это выглядит следующим образом:

container = tk.Frame(...)
text = tk.Text(container, ...)
scrollbar = tk.Scrollbar(container, ...)
scrollbar.pack(side="right", fill="y")
text.pack(side="left", fill="both", expand=True)

Вот и все. Теперь, независимо от размера вашего контейнера из-за изменения размера окна и т.д., Полоса прокрутки всегда будет прикрепляться к текстовому виджету. Затем вы обрабатываете эту группу контейнеров, текстовый виджет и полосу прокрутки в виде единого виджета, добавляя его ко всему графическому интерфейсу.

Обратите внимание, что вы также можете использовать сетку. Пакет проще, если у вас есть только вертикальная полоса прокрутки. Если у вас есть горизонтальные и вертикальные полосы прокрутки, сетка имеет немного больше смысла.

Чтобы завершить иллюзию, вы можете установить ширину границы текстового виджета равным нулю и установить границу ширины содержащего фрейма равным 1 с рельефом затонувшего, а полоса прокрутки будет отображаться в виде текстового виджета.

Вот полный рабочий пример, который выглядит более или менее похожим на ваш пример:

import Tkinter as tk

win = tk.Tk()

win.configure(background="#808000")

frame1 = tk.Frame(win,width=80, height=80,bg = '#ffffff',
                  borderwidth=1, relief="sunken")
scrollbar = tk.Scrollbar(frame1) 
editArea = tk.Text(frame1, width=10, height=10, wrap="word",
                   yscrollcommand=scrollbar.set,
                   borderwidth=0, highlightthickness=0)
scrollbar.config(command=editArea.yview)
scrollbar.pack(side="right", fill="y")
editArea.pack(side="left", fill="both", expand=True)
frame1.place(x=10,y=30)

win.mainloop()

Лично я не рекомендую делать глобальный импорт, и я не рекомендую использовать место, но я хотел, чтобы это было как можно ближе к вашему оригиналу.