【问题标题】:Tkinter: How to make a fixed canvas size with scroll bars that resize to the windowTkinter:如何使用调整到窗口大小的滚动条制作固定的画布大小
【发布时间】:2019-10-01 19:20:10
【问题描述】:

我正在尝试使用滚动条创建固定大小的画布小部件。有问题的画布可能非常大,并且几乎肯定会比包含它的框架大得多。我想将画布保持在固定大小,但能够调整包含它的窗口的大小。我遇到的问题是我不知道如何将滚动条绑定到窗口边缘。

我已经尝试过 .pack 和 .grid。 .grid 的明显问题是它只会将滚动条放在画布旁边。不幸的是,画布必须有一个固定的大小,总是比窗口大。每当我 .pack 时,画布似乎会随着窗口调整大小,即使我明确禁用展开并将填充设置为无。

为了清楚地看到画布区域,我已将背景设置为黑色。


import tkinter as tk
from tkinter import *


class DialogueCreation(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        self.xbar = tk.Scrollbar(parent, orient=HORIZONTAL)
        self.xbar.pack(side=BOTTOM, fill=X)

        self.ybar = tk.Scrollbar(parent)
        self.ybar.pack(side=RIGHT, fill=Y)

        self.item_canvas = tk.Canvas(parent, width=5000, height=5000, xscrollcommand=self.xbar.set, yscrollcommand=self.ybar.set)
        self.item_canvas.pack(side=LEFT, expand=FALSE, fill=None)
        self.item_canvas.configure(background='black')


if __name__ == '__main__':
    root = tk.Tk()
    DialogueCreation(root)
    root.title("Editor")
    root.mainloop()


画布是一个巨大的 5000x5000,所以当窗口很小的时候我肯定可以滚动。我希望滚动条与窗口边缘保持齐平,而无需调整画布大小。无论窗口有多大或多小,滚动条都会保持休眠状态。我假设画布正在随窗口调整大小,这绝对不是预期的结果。

最终,此画布上将显示多张图像,并且这些图像在画布上的位置不得更改。我认为问题不在于我如何绑定滚动条(我检查了该网站上的其他几篇帖子以确保),但如果我错过了类似的明显内容,这也不是不正常的。

【问题讨论】:

  • 我必须在示例代码中添加以下行才能看到画布:self.pack(side=tk.LEFT, expand=tk.TRUE, fill=tk.BOTH) 到末尾DialogueCreation init 函数。

标签: python tkinter scrollbar tkinter-canvas


【解决方案1】:

当您说要创建固定大小的画布时,我假设您的意思是您希望可绘制区域具有固定大小,而不是画布的可视部分具有固定大小。

为此,您需要将scrollregion 属性设置为可绘制区域。您可以使用widthheight 属性来设置画布可见部分的大小。

此外,连接滚动条是两条路:您必须配置画布以更新滚动条,并配置滚动条以滚动画布。

注意:您将DialogCreation 设为Frame,但您将所有小部件直接放在父级中。这是非常不寻常的,而且不是最好的方法。我建议像你一样从Frame 继承,但是所有的小部件都应该放在self 而不是父级。

当你这样做时,你需要确保你在DialogCreation的实例上调用pack,例如:

dr = DialogueCreation(root)
dr.pack(fill="both", expand=True)

使用包

对于pack,如果您希望在用户调整窗口大小时可见部分增大或缩小,则应将expand 选项设置为True

我的个人经验是,如果将小部件创建与小部件布局分开,代码更易于理解和维护。以下代码显示了我将如何使用pack 重写您的代码。注意配置xbarybar 以及设置scrollregion 的附加行。

class DialogueCreation(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        self.xbar = tk.Scrollbar(self, orient=HORIZONTAL)
        self.ybar = tk.Scrollbar(self)
        self.item_canvas = tk.Canvas(self, width=400, height=400,
                                     xscrollcommand=self.xbar.set,
                                     yscrollcommand=self.ybar.set)

        self.xbar.configure(command=self.item_canvas.xview)
        self.ybar.configure(command=self.item_canvas.yview)

        self.item_canvas.configure(scrollregion=(0,0,4999,4999))
        self.item_canvas.configure(background='black')

        self.xbar.pack(side=BOTTOM, fill=X)
        self.ybar.pack(side=RIGHT, fill=Y)
        self.item_canvas.pack(side=LEFT, expand=TRUE, fill=BOTH)

使用网格

.grid 的一个明显问题是它只会将滚动条放在画布旁边。

我根本不认为这很明显。 grid 没有这样的限制。您可以将滚动条放在您想要的任何位置。

grid 要记住的重要一点是,当整个窗口改变大小时,行和列不会自动增长或缩小。您必须明确告诉 tkinter 哪些行和哪些列要增长和缩小。

要达到与使用pack 相同的效果,您需要配置零行、零列以给予所有额外空间。你可以通过给他们一个大于零的weight 来做到这一点。

要使用grid 而不是pack,请将上面示例的最后三行替换为以下六行:

self.item_canvas.grid(row=0, column=0, sticky="nsew")
self.xbar.grid(row=1, column=0, sticky="ew")
self.ybar.grid(row=0, column=1, sticky="ns")
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)

【讨论】:

  • 问题是滚动区域设置。我最初将滚动条配置为更新,但在我疯狂的代码编辑中必须删除这些行。我遇到的 .grid 问题是,在没有设置滚动区域的情况下,它会强制滚动条始终位于画布的最边缘,这超出了窗口的范围。谢谢。
  • @Brandon:这不是网格的问题。网格的使用与滚动条的工作方式完全无关。
  • 我明白了,我的误解不是滚动条的功能。问题在于小部件几何。使用 .grid 放置滚动条时,它们被放置在画布下方和旁边。因为画布大小是固定的并且没有设置滚动区域,所以滚动条是不可见的,除非窗口被扩展到画布的大尺寸。设置滚动区域允许画布的可视区域调整大小而不调整画布本身的大小,因此滚动条能够在窗口中保持可见。至少这是我的理解。
猜你喜欢
  • 1970-01-01
  • 2018-03-01
  • 2018-05-11
  • 2021-04-27
  • 1970-01-01
  • 2019-07-02
  • 2016-07-26
  • 2021-04-06
  • 2017-04-08
相关资源
最近更新 更多