gpt4 book ai didi

python - 在 Tkinter 中为一组小部件添加滚动条

转载 作者:IT老高 更新时间:2023-10-28 20:24:48 24 4
gpt4 key购买 nike

我正在使用 Python 从日志文件中解析条目,并使用 Tkinter 显示条目内容,到目前为止它非常出色。输出是一个标签小部件的网格,但有时行数超出了屏幕上可以显示的数量。我想加一个滚动条,看起来应该很简单,但我想不通。

文档暗示只有 List、Textbox、Canvas 和 Entry 小部件支持滚动条界面。这些似乎都不适合显示小部件网格。可以在 Canvas 小部件中放置任意小部件,但您似乎必须使用绝对坐标,所以我无法使用网格布局管理器?

我尝试将小部件网格放入 Frame 中,但这似乎不支持滚动条界面,所以这不起作用:

mainframe = Frame(root, yscrollcommand=scrollbar.set)

任何人都可以提出解决此限制的方法吗?我讨厌不得不在 PyQt 中重写并将我的可执行图像大小增加这么多,只是为了添加一个滚动条!

最佳答案

概述

您只能将滚动条与几个小部件相关联,而根小部件和 Frame 不属于该小部件组。

至少有几种方法可以做到这一点。如果您需要一组简单的垂直或水平小部件,您可以使用文本小部件和 window_create 方法来添加小部件。这种方法很简单,但不允许对小部件进行复杂的布局。

更常见的通用解决方案是创建一个 Canvas 小部件并将滚动条与该小部件相关联。然后,在该 Canvas 中嵌入包含标签小部件的框架。确定框架的宽度/高度并将其输入到 Canvas scrollregion 选项中,以便滚动区域与框架的大小完全匹配。

为什么将小部件放在框架中而不是直接放在 Canvas 中?附加到 Canvas 的滚动条只能滚动使用 create_ 方法之一创建的项目。您不能使用 packplacegrid 滚动添加到 Canvas 的项目。通过使用框架,您可以在框架内使用这些方法,然后为框架调用一次create_window

直接在 Canvas 上绘制文本项并不是很困难,因此如果框架嵌入在 Canvas 中的解决方案看起来过于复杂,您可能需要重新考虑这种方法。由于您正在创建一个网格,因此每个文本项的坐标将非常容易计算,特别是如果每​​一行的高度相同(如果您使用的是单一字体,则可能是这样)。

要直接在 Canvas 上绘图,只需确定您正在使用的字体的行高(并且有相应的命令)。然后,每个 y 坐标为 row*(lineheight+spacing)。 x 坐标将是基于每列中最宽项的固定数字。如果你给所有的东西一个它所在的列的标签,你可以用一个命令调整一个列中所有项目的 x 坐标和宽度。

面向对象的解决方案

以下是使用面向对象方法的框架嵌入 Canvas 解决方案的示例:

import tkinter as tk

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

tk.Frame.__init__(self, parent)
self.canvas = tk.Canvas(self, borderwidth=0, background="#ffffff")
self.frame = tk.Frame(self.canvas, background="#ffffff")
self.vsb = tk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.vsb.set)

self.vsb.pack(side="right", fill="y")
self.canvas.pack(side="left", fill="both", expand=True)
self.canvas.create_window((4,4), window=self.frame, anchor="nw",
tags="self.frame")

self.frame.bind("<Configure>", self.onFrameConfigure)

self.populate()

def populate(self):
'''Put in some fake data'''
for row in range(100):
tk.Label(self.frame, text="%s" % row, width=3, borderwidth="1",
relief="solid").grid(row=row, column=0)
t="this is the second column for row %s" %row
tk.Label(self.frame, text=t).grid(row=row, column=1)

def onFrameConfigure(self, event):
'''Reset the scroll region to encompass the inner frame'''
self.canvas.configure(scrollregion=self.canvas.bbox("all"))

if __name__ == "__main__":
root=tk.Tk()
example = Example(root)
example.pack(side="top", fill="both", expand=True)
root.mainloop()

程序解决方案

这是一个不使用类的解决方案:

import tkinter as tk

def populate(frame):
'''Put in some fake data'''
for row in range(100):
tk.Label(frame, text="%s" % row, width=3, borderwidth="1",
relief="solid").grid(row=row, column=0)
t="this is the second column for row %s" %row
tk.Label(frame, text=t).grid(row=row, column=1)

def onFrameConfigure(canvas):
'''Reset the scroll region to encompass the inner frame'''
canvas.configure(scrollregion=canvas.bbox("all"))

root = tk.Tk()
canvas = tk.Canvas(root, borderwidth=0, background="#ffffff")
frame = tk.Frame(canvas, background="#ffffff")
vsb = tk.Scrollbar(root, orient="vertical", command=canvas.yview)
canvas.configure(yscrollcommand=vsb.set)

vsb.pack(side="right", fill="y")
canvas.pack(side="left", fill="both", expand=True)
canvas.create_window((4,4), window=frame, anchor="nw")

frame.bind("<Configure>", lambda event, canvas=canvas: onFrameConfigure(canvas))

populate(frame)

root.mainloop()

关于python - 在 Tkinter 中为一组小部件添加滚动条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3085696/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com