Python tkinter canvas 不在自己的行和列中

Python tkinter canvas not staying within its own row and column

我无法让 tkinter.Canvas 保持在网格管理器中其行和列的范围内。

This is how it looks to begin with

As required, the scrollbars appear when the window is shrunk enough that the text won't all fit

When the scrollbars are used, it becomes evident that the canvas is still behind the scrollbars

我需要弄清楚如何调整 canvas 以使其保持在网格管理器的第 0 行第 0 列内,并且不会溢出到第 1 行和第 1 列或更远的地方。以下是出现问题的主要代码

import tkinter as tk

from AutoScrollbar import *

class ScrollText(tk.Frame):

    def __init__(self, parent, writing, wrap, *args, **kwargs):

        tk.Frame.__init__(self, parent, *args, **kwargs)

        self.rowconfigure(0, weight = 1)
        self.columnconfigure(0, weight = 1)

        self.xscrlbr = AutoScrollbar(self, orient = 'horizontal')
        self.xscrlbr.grid(row = 1, column = 0, sticky = 'we')
        self.yscrlbr = AutoScrollbar(self)
        self.yscrlbr.grid(row = 0, column = 1, sticky = 'ns')

        self.canv = tk.Canvas(self)
        self.canv.grid(column = 0, row = 0, sticky = 'news')

        self.xscrlbr.config(command = self.canv.xview)
        self.yscrlbr.config(command = self.canv.yview)

        self.text = tk.Label(self, text = writing, wraplength = wrap,
                             justify = 'left')
        self.text_id = self.canv.create_window(0, 0,
                                window = self.text, anchor = 'nw')
        self.canv.config(xscrollcommand = self.xscrlbr.set,
                         yscrollcommand = self.yscrlbr.set,
                         scrollregion = (0, 0, 100, 100))

        self.yscrlbr.lift(self.text)
        self.xscrlbr.lift(self.text)

        self.canv.bind('<Configure>', self.OnCanvasConfigure)
        self.text.bind('<Configure>', self._configure_window)

    def OnCanvasConfigure(self, event):

        width = max(event.width, self.text.winfo_reqwidth())
        height = max(event.height, self.text.winfo_reqheight())

        self.canv.itemconfigure(self.text_id, width = width, height = height)

    def _configure_window(self, event):
      
        size = (self.text.winfo_reqwidth(), self.text.winfo_reqheight())
        self.canv.config(scrollregion = '0 0 %s %s' % size)

以下是 AutoScrollbar 代码,尽管问题行为与普通 tkinter.Scrollbar 相同,所以这不是问题所在。

import tkinter as tk

class AutoScrollbar(tk.Scrollbar):

    def set(self, low, high):

        if float(low) <= 0.0 and float(high) >= 1.0:

            self.tk.call("grid", "remove", self)

        else:

            self.grid()

        tk.Scrollbar.set(self, low, high)

最后,这是我用来调用它的示例代码:据我所知这里也没有问题。

import tkinter as tk
from ScrollText import *

class Template(tk.Tk):

    def __init__(self):

        tk.Tk.__init__(self)

        self.state('zoomed')

        self.rowconfigure(0, weight = 1)
        self.columnconfigure(0, weight = 1)

        message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pellentesque elit ullamcorper dignissim cras. Venenatis lectus magna fringilla urna. Augue lacus viverra vitae congue eu consequat ac felis. Arcu bibendum at varius vel pharetra vel turpis nunc eget. Pellentesque nec nam aliquam sem et tortor consequat. Dignissim suspendisse in est ante in. Diam volutpat commodo sed egestas egestas fringilla phasellus. Est placerat in egestas erat imperdiet sed euismod nisi porta. Turpis tincidunt id aliquet risus feugiat in ante. Tristique nulla aliquet enim tortor at. Nibh ipsum consequat nisl vel pretium. Ultricies mi quis hendrerit dolor magna eget est lorem ipsum. Leo vel orci porta non pulvinar neque laoreet suspendisse interdum. Volutpat odio facilisis mauris sit amet massa vitae tortor. Vel pretium lectus quam id. Egestas integer eget aliquet nibh praesent. Senectus et netus et malesuada fames ac. Iaculis eu non diam phasellus vestibulum lorem. Ut eu sem integer vitae justo eget magna fermentum."

        scrollableText = ScrollText(self, message, 500)
        scrollableText.grid(row = 0, column = 0, sticky = 'news', pady = 20, padx = 20)

if __name__ == '__main__':

    test = Template()
    test.mainloop()

您将标签创建为框架的子项,然后将其嵌入到 canvas 中。如果您要在 canvas 中嵌入一个小部件,它应该是 canvas.

的子项
self.text = tk.Label(self.canv, text = writing, wraplength = wrap,justify = 'left')
#                    ^^^^^^^^^