23
Фев
2016

Несколько фреймов в столбец и scrollbar к ним

Имеется группа подобных фреймов с некими элементами. Хочу расположить эти фреймы в виде колоночки со скроллбаром справа и всю эту конструкцию упаковать в один объёмлющий фрейм. Делаю так:

frame = Frame(mainWindow) # фрейм в котором будет расположен столбец фреймов с скроллом
frame.grid()
listbox = Listbox(dialogsFrame)
listbox.pack(side = LEFT, fill = Y)
scroll = Scrollbar(dialogsFrame)
scroll.pack(side = RIGHT, fill = Y)
listbox.config(yscrollcommand = scroll.set)
scroll.config(command = listbox.yview)

И затем я в listbox упаковываю мои фреймы типа frames[i].grid(row = i, column = 0). В итоге получается нужная конструкция, однако скроллбар не работает. Т.е. на нём нет ползунка и он вообще не активен. При этом по дефолту размер frame оказывается достаточен для того, чтобы на скроллбаре не было ползунка (т.е. все подфреймы видны). При ресайзе окна добиться появления ползунка не удаётся. Скроллбар хочется сделать т.к. возможен случай когда подфреймов будет слишком много и окошко вылезет за пределы монитора. Как это сделать?

Окромя исходного фрейма в окне могут располагаться другие элементы. Хочется сделать конструкцию независящей от размеров этих элементов и самого фрейма. Т.е. если юзер ресайзит окно, то в определённый момент (если высота окна слишком маленькая) скроллбар активируется. Хочется только задать ограничение на само окно (к примеру, установить высоту окна в некую долю от разрешения по вертикали) и ограничения на ресайз некоторых элементов, соседствующих с фреймом, а сам фрейм пусть ресайзится как хочет, только чтоб скроллбар появлялся и корректно работал.

UDP[26.02.2016]: нашёл этот пример на английском stackoverflow. На его основе сделал следующий тестовый код:

from tkinter import *

root = Tk()

topButton = Button(root, text = 'Кнопка сверху')
topButton.grid(row = 0, column = 0)
lowFrame = Frame(root)
lowFrame.grid(row = 1, column = 0)

canvas = Canvas(lowFrame)
frame = Frame(canvas)
myscrollbar = Scrollbar(lowFrame, orient = 'vertical', command = canvas.yview)
canvas.configure(yscrollcommand = myscrollbar.set)
myscrollbar.pack(side = 'right', fill = Y)
canvas.pack(side = 'left')
canvas.create_window((0, 0), window = frame, anchor = 'nw')
def conf(event):
    canvas.configure(scrollregion = canvas.bbox('all'))
frame.bind('<Configure>', conf)

for i in range(50):
    b = Button(frame, text = str(i))
    b.grid(row = i, column = 0)

root.mainloop()

Он вполне работает, однако возникли пара вопросов:

  1. Что делает canvas.create_window()? Что это за окно, где оно создаётся?
  2. Мы биндим frame.bind('<Configure>', conf). Можно проверить что событие происходит каждый раз при использовании скролла. Почему при использовании скролла происходит событие, связанное со фреймом?
  3. Что делает эта штука: canvas.configure(scrollregion = canvas.bbox('all'))? Почему её необходимо выполнять каждый раз при скролле, почему недостаточно выполнить один раз при инициализации программы?
  4. Нет ли способа забиндить событие (см. 2 и 3) без явного определения дополнительной функции в программе? Заюзать лямбда-выражения, или что-то в таком духе?

Источник: https://ru.stackoverflow.com/questions/496427/%D0%9D%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%BE-%D1%84%D1%80%D0%B5%D0%B9%D0%BC%D0%BE%D0%B2-%D0%B2-%D1%81%D1%82%D0%BE%D0%BB%D0%B1%D0%B5%D1%86-%D0%B8-scrollbar-%D0%BA-%D0%BD%D0%B8%D0%BC

Share

Тебе может это понравится...