Как обновить размер полосы прокрутки tkinter для размера холста

#python #tkinter #tkinter-canvas

#python #tkinter #tkinter-холст

Вопрос:

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

 import tkinter
from tkinter import ttk



root = tkinter.Tk()
root.state("zoomed")
bigframe = tkinter.Frame(root)
bigframe.pack(fill="both", expand=1)
canvas = tkinter.Canvas(bigframe)
canvas.pack(side="left", fill="both", expand=1)
scrollbarv = ttk.Scrollbar(bigframe, orient="vertical", command=canvas.yview)
scrollbarh = ttk.Scrollbar(bigframe, orient="horizontal", command=canvas.xview)
scrollbarv.pack(side="right", fill="y")
scrollbarh.pack(side="bottom", fill="x")
canvas.configure(yscrollcommand=scrollbarv.set, xscrollcommand=scrollbarh.set)
canvas.bind("<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
mainframe = tkinter.Frame(canvas)
canvas.create_window((0, 0), window=mainframe, anchor="nw")


i = 1
text = "Hello World! "
def click():
    global i
    global text
    for t in range(10):
        i  = 1
        text  = "Hello World! "
        tkinter.Label(mainframe, text=text).pack()
    scrollbar = ttk.Scrollbar(bigframe, orient="vertical", command=canvas.yview)
    scrollbar.pack(side="right", fill="y")

button = tkinter.Button(mainframe, text="Click me!", command=click)
button.pack()

root.mainloop()
 

Это то, что происходит, когда я нажимаю кнопку 4 раза:

Я считаю, что небольшая горизонтальная полоса прокрутки связана с тем, что я говорю canvas.pack(side="left", fill="both", expand=1) , но если я скажу side="top , то вертикальные полосы прокрутки не охватывают высоту холста. Есть ли какой-то конкретный фрагмент кода, который вызывает проблему с несколькими полосами прокрутки или проблему с горизонтальной полосой? И если да, то как мне это исправить?

Ответ №1:

Вы должны уничтожить старую полосу прокрутки, прежде чем добавлять новую. Просто добавьте scrollbar.destroy() в свою функцию щелчка, как я сделал ниже:

 def click():
    global i
    global text
    for t in range(10):
        i  = 1
        text  = "Hello World! "
        tkinter.Label(mainframe, text=text).pack()
    scrollbar = ttk.Scrollbar(bigframe, orient="vertical", command=canvas.yview)
    scrollbar.destroy()
    scrollbar.pack(side="right", fill="y")
 

Я внес следующие изменения в ваш код. Сначала это не работает, однако, если я изменяю размер окна, оно работает отлично.

 import tkinter
from tkinter import ttk



root = tkinter.Tk()
root.state("zoomed")
bigframe = tkinter.Frame(root)
bigframe.pack(fill="both", expand=1)
canvas = tkinter.Canvas(bigframe)
canvas.pack(side="left", fill="both", expand=1)
scrollbarv = ttk.Scrollbar(bigframe, orient="vertical", 
command=canvas.yview)
scrollbarh = ttk.Scrollbar(root, orient="horizontal", 
command=canvas.xview)
scrollbarv.pack(side="right", fill="y")
scrollbarh.pack(side="bottom", fill="x")
canvas.configure(yscrollcommand=scrollbarv.set, 
xscrollcommand=scrollbarh.set)
canvas.bind("<Configure>", lambda e: 
canvas.configure(scrollregion=canvas.bbox("all")))
mainframe = tkinter.Frame(canvas)
canvas.create_window((0, 0), window=mainframe, anchor="nw")


i = 1
text = "Hello World! "

def updateScrollRegion():
    canvas.update_idletasks()
    canvas.config(scrollregion=mainframe.bbox())

def click():
    global i, scrollbarv, text
    for t in range(10):
        i  = 1
        text  = "Hello World! "
        tkinter.Label(mainframe, text=text).pack()

button = tkinter.Button(mainframe, text="Click me!", command=click)
button.pack()

root.mainloop()
 

Комментарии:

1. Когда я пытаюсь это сделать, полоса прокрутки становится серой и не прокручивается. Тем не менее, спасибо за предложение. Знаете ли вы, нужно ли перемещать некоторые строки, чтобы он работал с этим методом?

2. Спасибо за ваше предложение. Используя вашу идею, я смог исправить это и устранить проблему с несколькими столбцами, повозившись с некоторыми глобальными переменными

3. О, это здорово, никаких проблем. Не могли бы вы опубликовать рабочий код, я хотел бы его увидеть.

4. Я воспользовался вашим первым предложением и переместил команду destroy над командой ttk.Scrollbar, а глобальную полосу прокрутки разместил в верхней части функции. Я могу попробовать переделать код, если вы хотите, чтобы я, но я сделал это только в качестве примера, чтобы проиллюстрировать мою проблему, и это сильно отличается от моего основного программного кода.

5. Еще одна вещь, которую я изучил, это gist.github.com/novel-yet-trivial /… , который представляет собой двойную рамку полосы прокрутки от novel-yet-trivial, и он прекрасно работает, упрощая процесс