Python Tkinter:在 canvas 框架内添加滚动条
Python Tkinter: adding a scrollbar to frame within a canvas
我对 Tkinter 很陌生,但是,尽管如此,我还是被要求 "create" 一个简单的表格,用户可以在其中提供有关其工作状态的信息(这是我平时的一个副项目工作)。
由于我需要有相当多的文本小部件(用户需要提供有关文档状态或未解决问题等的评论),我想要一些东西 "scrollable" (沿着 y 轴).
我四处浏览寻找解决方案,经过反复试验,我发现了一些非常有效的方法。
基本上我创建了一个 canvas,在 canvas 里面有一个滚动条和一个框架。在框架内,我拥有我需要的所有小部件。
这是代码片段(只有一些实际的小部件,尤其是文本小部件):
from Tkinter import *
## My frame for form
class simpleform_ap(Tk):
# constructor
def __init__(self,parent):
Tk.__init__(self,parent)
self.parent = parent
self.initialize()
#
def initialize(self):
#
self.grid_columnconfigure(0,weight=1)
self.grid_rowconfigure(0,weight=1)
#
self.canvas=Canvas(self.parent)
self.canvas.grid(row=0,column=0,sticky='nsew')
#
self.yscrollbar = Scrollbar(self,orient=VERTICAL)
self.yscrollbar.grid(column =4, sticky="ns")
#
self.yscrollbar.config(command=self.canvas.yview)
self.yscrollbar.pack(size=RIGTH,expand=FALSE)
#
self.canvas.config(yscrollcommand=self.yscrollbar.set)
self.canvas.pack(side=LEFT,expand=TRUE,fill=BOTH)
#
self.frame1 = Frame(self.canvas)
self.canvas.create_window(0,0,window=self.frame1,anchor='nw')
# Various Widget
# Block Part
# Label
self.labelVariableIP = StringVar() # Label variable
labelIP=Label(self.frame1,textvariable=self.labelVariableIP,
anchor="w",
fg="Black")
labelIP.grid(column=0,row=0,columnspan=1,sticky='EW')
self.labelVariableIP.set(u"IP: ")
# Entry: Single line of text!!!!
self.entryVariableIP =StringVar() # variable for entry field
self.entryIP =Entry(self.frame1,
textvariable=self.entryVariableIP,bg="White")
self.entryIP.grid(column = 1, row= 0, sticky='EW')
self.entryVariableIP.set(u"IP")
# Update Button or Enter
button1=Button(self.frame1, text=u"Update",
command=self.OnButtonClickIP)
button1.grid(column=2, row=0)
self.entryIP.bind("<Return>", self.OnPressEnterIP)
#...
# Other widget here
#
# Some Text
# Label
self.labelVariableText = StringVar() # Label variable
labelText=Label(self.frame1,textvariable=
self.labelVariableText,
anchor="nw",
fg="Black")
labelText.grid(column=0,row=curr_row,columnspan=1,sticky='EW')
self.labelVariableTexta.set(u"Insert some texts: ")
# Text
textState = TRUE
self.TextVar=StringVar()
self.mytext=Text(self.frame1,state=textState,
height = text_height, width = 10,
fg="black",bg="white")
#
self.mytext.grid(column=1, row=curr_row+4, columnspan=2, sticky='EW')
self.mytext.insert('1.0',"Insert your text")
#
# other text widget here
#
self.update()
self.geometry(self.geometry() )
self.frame1.update_idletasks()
self.canvas.config(scrollregion=(0,0,
self.frame1.winfo_width(),
self.frame1.winfo_height()))
#
def release_block(argv):
# Create Form
form = simpleform_ap(None)
form.title('Release Information')
#
form.mainloop()
#
if __name__ == "__main__":
release_block(sys.argv)
正如我之前提到的,这个脚本非常有用,即使它有几个小问题,不是 "fundamental" 但有点烦人。
当我启动它时,我得到了这个(抱歉截屏不好):
enter image description here
可以看出,它只显示了网格的第一个 "column",而我想要所有的(在我的例子中它们应该是 4)
要查看所有字段,我必须手动(使用鼠标)调整 window 的大小。
我想要的是这样的(所有 4 列都在那里):
enter image description here
此外,滚动条并没有延伸到整个表单,而是位于 windows 的右下角。
虽然后一个问题(滚动条)我可以留下,但第一个问题更重要一些,因为我想让最终用户知道 "picture" 他们应该做什么,而不是需要调整 windows.
的大小
有人知道我应该如何处理吗?
我错过了什么?
在此先感谢您的帮助
在 class 的 __init__
方法中,您似乎没有设置 main window 的大小。你应该这样做,否则它只会将 window 设置为默认大小,这将只显示它可以显示的任何内容,在你的情况下,只有 1 列。因此,在 __init__
方法中,尝试将 self.geometry(str(your_width) + "x" + str(your_height))
放在 your_width
和 your_height
是您选择的任何整数,以便您在 window.
至于你的滚动条问题,我所要做的就是将你的滚动条添加到 canvas 的方式更改为 .pack()
并向其添加属性 fill = 'y' and side = RIGHT
,像这样:
self.yscrollbar.pack(side = 'right', fill = 'y')
此外,您不需要:
self.yscrollbar.config(command=self.canvas.yview)
self.yscrollbar.pack(size=RIGHT,expand=FALSE)
只需在创建滚动条时添加命令选项即可,如下所示:
self.scrollbar = Scrollbar(self,orient=VERTICAL,command=self.canvas.yview)
总而言之,以下更改应该会使您的代码按预期工作:
添加:
def __init__(self,parent):
Tk.__init__(self,parent)
self.parent = parent
self.initialize()
# Resize the window from the default size to make your widgets fit. Experiment to see what is best for you.
your_width = # An integer of your choosing
your_height = # An integer of your choosing
self.geometry(str(your_width) + "x" + str(your_height))
添加和编辑:
# Add `command=self.canvas.yview`
self.yscrollbar = Scrollbar(self,orient=VERTICAL,command=self.canvas.yview)
# Use `.pack` instead of `.grid`
self.yscrollbar.pack(side = 'right', fill = 'y')
删除:
self.yscrollbar.config(command=self.canvas.yview)
self.yscrollbar.pack(size=RIGHT,expand=FALSE)
我对 Tkinter 很陌生,但是,尽管如此,我还是被要求 "create" 一个简单的表格,用户可以在其中提供有关其工作状态的信息(这是我平时的一个副项目工作)。 由于我需要有相当多的文本小部件(用户需要提供有关文档状态或未解决问题等的评论),我想要一些东西 "scrollable" (沿着 y 轴).
我四处浏览寻找解决方案,经过反复试验,我发现了一些非常有效的方法。 基本上我创建了一个 canvas,在 canvas 里面有一个滚动条和一个框架。在框架内,我拥有我需要的所有小部件。
这是代码片段(只有一些实际的小部件,尤其是文本小部件):
from Tkinter import *
## My frame for form
class simpleform_ap(Tk):
# constructor
def __init__(self,parent):
Tk.__init__(self,parent)
self.parent = parent
self.initialize()
#
def initialize(self):
#
self.grid_columnconfigure(0,weight=1)
self.grid_rowconfigure(0,weight=1)
#
self.canvas=Canvas(self.parent)
self.canvas.grid(row=0,column=0,sticky='nsew')
#
self.yscrollbar = Scrollbar(self,orient=VERTICAL)
self.yscrollbar.grid(column =4, sticky="ns")
#
self.yscrollbar.config(command=self.canvas.yview)
self.yscrollbar.pack(size=RIGTH,expand=FALSE)
#
self.canvas.config(yscrollcommand=self.yscrollbar.set)
self.canvas.pack(side=LEFT,expand=TRUE,fill=BOTH)
#
self.frame1 = Frame(self.canvas)
self.canvas.create_window(0,0,window=self.frame1,anchor='nw')
# Various Widget
# Block Part
# Label
self.labelVariableIP = StringVar() # Label variable
labelIP=Label(self.frame1,textvariable=self.labelVariableIP,
anchor="w",
fg="Black")
labelIP.grid(column=0,row=0,columnspan=1,sticky='EW')
self.labelVariableIP.set(u"IP: ")
# Entry: Single line of text!!!!
self.entryVariableIP =StringVar() # variable for entry field
self.entryIP =Entry(self.frame1,
textvariable=self.entryVariableIP,bg="White")
self.entryIP.grid(column = 1, row= 0, sticky='EW')
self.entryVariableIP.set(u"IP")
# Update Button or Enter
button1=Button(self.frame1, text=u"Update",
command=self.OnButtonClickIP)
button1.grid(column=2, row=0)
self.entryIP.bind("<Return>", self.OnPressEnterIP)
#...
# Other widget here
#
# Some Text
# Label
self.labelVariableText = StringVar() # Label variable
labelText=Label(self.frame1,textvariable=
self.labelVariableText,
anchor="nw",
fg="Black")
labelText.grid(column=0,row=curr_row,columnspan=1,sticky='EW')
self.labelVariableTexta.set(u"Insert some texts: ")
# Text
textState = TRUE
self.TextVar=StringVar()
self.mytext=Text(self.frame1,state=textState,
height = text_height, width = 10,
fg="black",bg="white")
#
self.mytext.grid(column=1, row=curr_row+4, columnspan=2, sticky='EW')
self.mytext.insert('1.0',"Insert your text")
#
# other text widget here
#
self.update()
self.geometry(self.geometry() )
self.frame1.update_idletasks()
self.canvas.config(scrollregion=(0,0,
self.frame1.winfo_width(),
self.frame1.winfo_height()))
#
def release_block(argv):
# Create Form
form = simpleform_ap(None)
form.title('Release Information')
#
form.mainloop()
#
if __name__ == "__main__":
release_block(sys.argv)
正如我之前提到的,这个脚本非常有用,即使它有几个小问题,不是 "fundamental" 但有点烦人。
当我启动它时,我得到了这个(抱歉截屏不好): enter image description here
可以看出,它只显示了网格的第一个 "column",而我想要所有的(在我的例子中它们应该是 4) 要查看所有字段,我必须手动(使用鼠标)调整 window 的大小。 我想要的是这样的(所有 4 列都在那里): enter image description here
此外,滚动条并没有延伸到整个表单,而是位于 windows 的右下角。
虽然后一个问题(滚动条)我可以留下,但第一个问题更重要一些,因为我想让最终用户知道 "picture" 他们应该做什么,而不是需要调整 windows.
的大小有人知道我应该如何处理吗? 我错过了什么?
在此先感谢您的帮助
在 class 的 __init__
方法中,您似乎没有设置 main window 的大小。你应该这样做,否则它只会将 window 设置为默认大小,这将只显示它可以显示的任何内容,在你的情况下,只有 1 列。因此,在 __init__
方法中,尝试将 self.geometry(str(your_width) + "x" + str(your_height))
放在 your_width
和 your_height
是您选择的任何整数,以便您在 window.
至于你的滚动条问题,我所要做的就是将你的滚动条添加到 canvas 的方式更改为 .pack()
并向其添加属性 fill = 'y' and side = RIGHT
,像这样:
self.yscrollbar.pack(side = 'right', fill = 'y')
此外,您不需要:
self.yscrollbar.config(command=self.canvas.yview)
self.yscrollbar.pack(size=RIGHT,expand=FALSE)
只需在创建滚动条时添加命令选项即可,如下所示:
self.scrollbar = Scrollbar(self,orient=VERTICAL,command=self.canvas.yview)
总而言之,以下更改应该会使您的代码按预期工作:
添加:
def __init__(self,parent): Tk.__init__(self,parent) self.parent = parent self.initialize() # Resize the window from the default size to make your widgets fit. Experiment to see what is best for you. your_width = # An integer of your choosing your_height = # An integer of your choosing self.geometry(str(your_width) + "x" + str(your_height))
添加和编辑:
# Add `command=self.canvas.yview` self.yscrollbar = Scrollbar(self,orient=VERTICAL,command=self.canvas.yview) # Use `.pack` instead of `.grid` self.yscrollbar.pack(side = 'right', fill = 'y')
删除:
self.yscrollbar.config(command=self.canvas.yview) self.yscrollbar.pack(size=RIGHT,expand=FALSE)