Python, ткинтер и полоса прокрутки в сетке - PullRequest
0 голосов
/ 24 апреля 2020

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

У меня есть виджет LabelFrame, в котором у меня есть несколько меток и виджет ListBox. Я хочу, чтобы виджет ListBox имел полосу прокрутки. Кажется, я не могу заставить его работать.

Вот код ошибки:

    self.lbDates = tk.Listbox(master=group, width=12)
    self.lbDates.grid(row=3, column=1, padx=3, pady=3)

    self.scrollDates = tk.Scrollbar(self.lbDates, orient="vertical")
    self.scrollDates.config(command=self.lbDates.yview)
    self.scrollDates.grid(row=3, column=1)

    self.lbDates.config(yscrollcommand=self.scrollDates.set)

Несколько вопросов: должна ли полоса прокрутки находиться в одном и том же месте (то есть в той же строке сетки) и столбец) как виджет ListBox? Я предполагал, что так и должно быть, но учитывая, сколько у меня было проблем с этим, я чувствую, что должен спросить.

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

Что происходит, когда я запускаю этот код? Ну, я не вижу ListBox, но я вижу полосу прокрутки. Теперь, когда там должны быть данные (и я знаю, потому что я их заполняю), я вижу то, что вы можете себе представить, это правильная полоса прокрутки, хотя ListBox либо невидим, либо скрыт, либо еще что-то. Он мигает на долю секунды, когда он заполнен, но затем снова скрывается.

Я могу показать вам, на самом деле, пример этого.

enter image description here

У верхнего нет данных, а у второго есть данные. Конечно, вы не можете видеть данные, но вы можете видеть, что они должны быть там. И если я уберу полосу прокрутки, я получу ожидаемые данные в виджетах ListBox. Я хотел бы показать изображение момента, которое оно заполняет, прежде чем оно исчезнет, ​​но оно выглядит как один кадр, и я не могу его уловить.

Я уверен, что моя ошибка здесь должна быть чем-то очень простым, и Я очень надеюсь, что кто-то может помочь. Я использую tkinter для виджетов и Python 3.7.

Edit: я сделал некоторые изменения, как предложено ниже, так что мои ListBox и Scrollbar теперь существуют в Frame и этот Frame находится в объекте LabelFrame. Следующее:

    fr = tk.Frame(master = group)
    fr.grid(row=4, column=1)

    self.lbDates = tk.Listbox(master=fr, width=12)
    self.lbDates.pack()

    self.scrollDates = tk.Scrollbar(master=self.lbDates, orient="vertical")
    self.scrollDates.config(command=self.lbDates.yview)
    self.scrollDates.pack()

    self.lbDates.config(yscrollcommand=self.scrollDates.set)

К сожалению, нет никакой разницы, и я, похоже, испытываю те же проблемы, что и раньше.

1 Ответ

1 голос
/ 24 апреля 2020

полоса прокрутки должна находиться в том же пространстве (то есть в той же строке и столбце сетки), что и виджет ListBox?

Вам решать. Обычно вы , а не помещаете полосу прокрутки в список, так как это может скрыть некоторые данные в списке. Список и полоса прокрутки будут иметь одного и того же родителя. Если вы используете grid, обычно вертикальная полоса прокрутки находится в столбце непосредственно справа от списка.

Что происходит, когда я запускаю этот код? Ну, я не вижу ListBox, но я вижу полосу прокрутки.

Это потому, что список сокращается, чтобы соответствовать его дочерним элементам. Список есть, но он такой же широкий и высокий, как полоса прокрутки. Это еще одна причина, по которой вам не следует помещать полосу прокрутки внутри списка.


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

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

Чтобы это работало, списки и полосы прокрутки должны быть дочерними элементами фрейма.

Вот простой пример:

import tkinter as tk

root = tk.Tk()

lb_frame = tk.Frame(root, bd=1, relief="sunken")
listbox = tk.Listbox(lb_frame, bd=0, yscrollcommand=lambda *args: vsb.set(*args))
vsb = tk.Scrollbar(lb_frame, orient="vertical", command=listbox.yview)

vsb.pack(side="right", fill="y")
listbox.pack(side="left", fill="both", expand=True)

lb_frame.pack(padx=20, pady=20)

for i in range(1, 100):
    listbox.insert("end", f"Item {i}")

root.mainloop()

screenshot of window with listbox

...