Tkinter 笔记本中的可滚动页面
Scrollable page in Tkinter Notebook
对于一个项目,我需要为N个子文件(数据集)指定一个值,这个值可以是均匀分布的(这里省略),只需要一个起始值和一个增量,或者不均匀分布,这意味着每个子文件都有自己的价值。我决定使用笔记本来区分这两种输入方法。
由于子文件的数量可以达到数百个,我需要一个滚动条,在咨询 Google 之后我发现要以这种方式使用滚动条我需要使用 canvas 并在其中放置一个框架,其中包含我想要滚动浏览的所有内容。
数字每次都可能不同,所以我决定使用一个字典,它会被迭代填充,以包含所有 'entry frames',每个包含一个标签、一个输入字段和一个变量,汇总到一个自定义 class IterEntryField
。创建 class 实例后,它被打包在一个容器框架中。 for
循环结束后,容器框架被放置在一个 canvas 上,滚动条被赋予一个新的滚动区域。
from tkinter import *
from tkinter.ttk import Notebook
N = 25
class IterEntryField:
def __init__(self, frame, label):
self.frame = frame
self.label = label
def pack(self):
self.valLabel = Label(self.frame, text = self.label, anchor = 'w')
self.valLabel.pack(fill = X, side = LEFT)
self.variable = StringVar()
self.variable.set('0')
self.valEntry = Entry(self.frame, textvariable = self.variable)
self.valEntry.pack(fill = X, side = RIGHT)
def notebookpopup():
zSetupWindow = Toplevel(root)
zSetupWindow.geometry('{}x{}'.format(800, 300))
notebook = Notebook(zSetupWindow)
evspace = Frame(notebook)
notebook.add(evspace, text = "Evenly spaced values")
sOverflow = Label(evspace, text = 'Ignore this')
sOverflow.pack()
uevspace = Frame(notebook)
notebook.add(uevspace, text = "Individual values")
canvas = Canvas(uevspace, width = 800, height = 400)
vsb = Scrollbar(canvas, command=canvas.yview)
canvas.config(yscrollcommand = vsb.set)
canvas.pack(side = LEFT, fill = BOTH, expand = True)
vsb.pack(side = RIGHT, fill = Y)
entryContainer = Frame(canvas)
entryContainer.pack(fill = BOTH)
frameDict = {}
for i in range(0, N):
frameDict[i] = Frame(entryContainer)
frameDict[i].pack(fill = X)
entry = IterEntryField(frameDict[i], 'Z value for subfile {}'.format(i+1))
entry.pack()
canvas.create_window(200, 0, window = entryContainer)
canvas.config(scrollregion = (0,0,100,1000))
notebook.pack(fill = X)
root = Tk()
button = Button(root, text = 'new window', command = notebookpopup)
button.pack()
root.mainloop()
我在使用这段代码时遇到了三个问题:
页面非常短,只显示了几行。
我无法计算出 create_window
中的 "proper" 偏移量。我以为 0, 0
会把它放在 canvas 的左上角,但显然 window 的左上角被取而代之。这可能可以通过 canvasx
和 canvasy
方法的一些反向来解决,但我还没有找到任何方法。
输入字段和标签挤在一起,而不是占据 canvas 的整个宽度。当我只使用笔记本页面框架作为容器时,这不是问题。
您的第一个问题可以追溯到您如何 pack
您的笔记本。只需将 notebook.pack(...)
更改为以下内容:
notebook.pack(fill="both", expand=True)
第二个可以通过在 create_window
方法中指定 anchor
位置来解决:
canvas.create_window(0, 0, window = entryContainer, anchor="nw")
我不明白第三个问题是什么 - 它看起来完全符合预期。
对于一个项目,我需要为N个子文件(数据集)指定一个值,这个值可以是均匀分布的(这里省略),只需要一个起始值和一个增量,或者不均匀分布,这意味着每个子文件都有自己的价值。我决定使用笔记本来区分这两种输入方法。
由于子文件的数量可以达到数百个,我需要一个滚动条,在咨询 Google 之后我发现要以这种方式使用滚动条我需要使用 canvas 并在其中放置一个框架,其中包含我想要滚动浏览的所有内容。
数字每次都可能不同,所以我决定使用一个字典,它会被迭代填充,以包含所有 'entry frames',每个包含一个标签、一个输入字段和一个变量,汇总到一个自定义 class IterEntryField
。创建 class 实例后,它被打包在一个容器框架中。 for
循环结束后,容器框架被放置在一个 canvas 上,滚动条被赋予一个新的滚动区域。
from tkinter import *
from tkinter.ttk import Notebook
N = 25
class IterEntryField:
def __init__(self, frame, label):
self.frame = frame
self.label = label
def pack(self):
self.valLabel = Label(self.frame, text = self.label, anchor = 'w')
self.valLabel.pack(fill = X, side = LEFT)
self.variable = StringVar()
self.variable.set('0')
self.valEntry = Entry(self.frame, textvariable = self.variable)
self.valEntry.pack(fill = X, side = RIGHT)
def notebookpopup():
zSetupWindow = Toplevel(root)
zSetupWindow.geometry('{}x{}'.format(800, 300))
notebook = Notebook(zSetupWindow)
evspace = Frame(notebook)
notebook.add(evspace, text = "Evenly spaced values")
sOverflow = Label(evspace, text = 'Ignore this')
sOverflow.pack()
uevspace = Frame(notebook)
notebook.add(uevspace, text = "Individual values")
canvas = Canvas(uevspace, width = 800, height = 400)
vsb = Scrollbar(canvas, command=canvas.yview)
canvas.config(yscrollcommand = vsb.set)
canvas.pack(side = LEFT, fill = BOTH, expand = True)
vsb.pack(side = RIGHT, fill = Y)
entryContainer = Frame(canvas)
entryContainer.pack(fill = BOTH)
frameDict = {}
for i in range(0, N):
frameDict[i] = Frame(entryContainer)
frameDict[i].pack(fill = X)
entry = IterEntryField(frameDict[i], 'Z value for subfile {}'.format(i+1))
entry.pack()
canvas.create_window(200, 0, window = entryContainer)
canvas.config(scrollregion = (0,0,100,1000))
notebook.pack(fill = X)
root = Tk()
button = Button(root, text = 'new window', command = notebookpopup)
button.pack()
root.mainloop()
我在使用这段代码时遇到了三个问题:
页面非常短,只显示了几行。
我无法计算出
create_window
中的 "proper" 偏移量。我以为0, 0
会把它放在 canvas 的左上角,但显然 window 的左上角被取而代之。这可能可以通过canvasx
和canvasy
方法的一些反向来解决,但我还没有找到任何方法。输入字段和标签挤在一起,而不是占据 canvas 的整个宽度。当我只使用笔记本页面框架作为容器时,这不是问题。
您的第一个问题可以追溯到您如何 pack
您的笔记本。只需将 notebook.pack(...)
更改为以下内容:
notebook.pack(fill="both", expand=True)
第二个可以通过在 create_window
方法中指定 anchor
位置来解决:
canvas.create_window(0, 0, window = entryContainer, anchor="nw")
我不明白第三个问题是什么 - 它看起来完全符合预期。