Полоса прокрутки не работает, правильно ли установлена ​​область прокрутки? - PullRequest
0 голосов
/ 23 июня 2019

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

Когда я запускаю проект, ScrollingCenterFrame2 проходит за нижнюю часть окна, а изменение размера нерешить проблему.Что я здесь не так делаю?

Ниже приведен минимально воспроизводимый пример моего кода

from tkinter import *
from tkinter import ttk

class ScrollingCenterFrame2(ttk.Frame):
    #TODO: Implement this to replace the current SCF
    def __init__(self, parent):
        ttk.Frame.__init__(self, parent)

        cfTitle = ttk.Label(self, text="Mission Options")
        cfTitle.pack()

        self.app = app
        self.parent = parent

        # create canvas and scrollbar
        self.vsb = ttk.Scrollbar(self, orient=VERTICAL)
        self.vsb.pack(side=RIGHT, fill=Y)
        self.canvas = Canvas(self, highlightthickness=0, bg="#ededed", height=10, width=10)
        self.canvas.configure(yscrollcommand=self.vsb.set)
        self.canvas.pack(side=LEFT, fill=BOTH, expand=True)
        self.vsb.configure(command=self.canvas.yview)

        # add bindings for mousewheel
        self.canvas.bind("<Enter>", self._bind_mouse)
        self.canvas.bind("<Leave>", self._unbind_mouse)


        self.inner  = ttk.Frame(self.canvas)
        self.inner_id = self.canvas.create_window((4,4), window=self.inner, anchor=NW)

        self.inner.bind("<Configure>", self._configureInner)
        self.canvas.bind("<Configure>", self._configureCanvas)

    #end init


    def _bind_mouse(self, event=None):
        self.canvas.bind_all("<4>", self._on_mousewheel)
        self.canvas.bind_all("<5>", self._on_mousewheel)
        self.canvas.bind_all("<MouseWheel>", self._on_mousewheel)


    def _unbind_mouse(self, event=None):
        self.canvas.unbind_all("<4>")
        self.canvas.unbind_all("<5>")
        self.canvas.unbind_all("<MouseWheel>")


    def _on_mousewheel(self, event):
        """Linux uses event.num; Windows / Mac uses event.delta"""
        if event.num == 4 or event.delta > 0:
            self.canvas.yview_scroll(-1, "units")
        elif event.num == 5 or event.delta < 0:
            self.canvas.yview_scroll(1, "units")


    def _configureInner(self, event=None):
        #TODO: Fix the bug in here

        # update the scrollbars to match the size of the inner frame
        #size = (self.inner.winfo_width(), self.inner.winfo_height())
        #self.canvas.config(scrollregion="0 0 %s %s" % size)
        bbox = self.canvas.bbox("all")
        self.canvas.config(scrollregion=bbox)
        if self.inner.winfo_reqwidth() >= self.canvas.winfo_width():
            # update the canvas's width to fit the inner frame
            # only works before mainloop
            self.canvas.config(width=self.inner.winfo_reqwidth())
        screen_h = self.winfo_screenheight()
        height   = self.parent.winfo_rooty() + self.parent.winfo_height() - self.canvas.winfo_height() + self.inner.winfo_reqheight()
        if height < screen_h:
            self.canvas.configure(height=self.inner.winfo_reqheight())
    #end _configureInner


    def _configureCanvas(self, event=None):
        if self.inner.winfo_reqwidth() < self.canvas.winfo_width():
            self.canvas.itemconfigure(self.inner_id, width=self.canvas.winfo_width())
        elif self.inner.winfo_reqwidth() > self.canvas.winfo_width():
            self.canvas.config(width=self.inner.winfo_reqwidth())
    #end _configureCanvas

#end class ScrollingCenterFrame2


if __name__ == "__main__":
    app = Tk()
    f = ScrollingCenterFrame2(app)
    f.pack(expand=True, fill="both")

    for x in range(1,50):
        l = ttk.Label(f.inner, text=("Testing", x))
        l.pack(expand=True, fill=X)

    app.mainloop()

Как вы можете видеть здесь, количество объектов обрезается, а изменение размера неисправить проблему с полосой прокрутки

1 Ответ

0 голосов
/ 01 июля 2019

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

Первое, что вам нужноdo это удалить код, который изменяет высоту внутреннего фрейма.Этот фрейм должен быть достаточно высоким, чтобы вместить его содержимое, и tkinter сделает это автоматически, без необходимости что-либо делать.

Итак, удалите эти строки кода:

if (self.inner.winfo_reqheight() < self.canvas.winfo_height()) or (self.inner.winfo_height() < self.canvas.winfo_height()):
    self.canvas.itemconfigure(self.inner_id, height=self.canvas.winfo_height())

Второе, что вам нужно сделать, это настроить область прокрутки на достаточно большую, чтобы включить все на холсте.Обычный способ сделать это - заставить холст сообщать вам ограничивающую рамку всего на экране (с self.canvas.bbox('all')) и использовать ее для значения scrollregion.

Другими словами, заменитьэто:

size = (self.inner.winfo_width(), self.inner.winfo_height())
self.canvas.config(scrollregion="0 0 %s %s" % size)

с этим:

bbox = self.canvas.bbox("all")
self.canvas.config(scrollregion=bbox)
...