Python 带tkinter的可调整大小的可滚动画布
下面是我为一个非常简单的gui编写的代码:Python 带tkinter的可调整大小的可滚动画布,python,canvas,tkinter,resize,scrollable,Python,Canvas,Tkinter,Resize,Scrollable,下面是我为一个非常简单的gui编写的代码: from Tkinter import * class my_gui(Frame): def __init__(self): # main tk object self.root = Tk() # init Frame Frame.__init__(self, self.root) # create frame (gray window) s
from Tkinter import *
class my_gui(Frame):
def __init__(self):
# main tk object
self.root = Tk()
# init Frame
Frame.__init__(self, self.root)
# create frame (gray window)
self.frame=Frame(self.root,width=100,height=100)
self.frame.grid(row=0,column=0)
self.__add_scroll_bars()
self.__create_canvas()
self.__add_plot()
def __create_canvas(self):
# create white area in the window for plotting
# width and height are only the visible size of the white area, scrollregion is the area the user can see by scrolling
self.canvas = Canvas(self.frame,bg='#FFFFFF',width=300,height=300,scrollregion=(0,0,500,500))
# with this command the window is filled with the canvas
self.canvas.pack(side=LEFT,expand=True,fill=BOTH)
# position and size of the canvas is used for configuration of the scroll bars
self.canvas.config(xscrollcommand=self.hbar.set, yscrollcommand=self.vbar.set)
# add command to the scroll bars to scroll the canvas
self.hbar.config(command = self.canvas.xview)
self.vbar.config(command = self.canvas.yview)
def __add_scroll_bars(self):
# add scroll bars
self.hbar=Scrollbar(self.frame,orient=HORIZONTAL)
self.hbar.pack(side=BOTTOM,fill=X)
self.vbar=Scrollbar(self.frame,orient=VERTICAL)
self.vbar.pack(side=RIGHT,fill=Y)
def __add_plot(self):
# create a rectangle
self.canvas.create_polygon(10, 10, 10, 150, 200, 150, 200, 10, fill="gray", outline="black")
def mainLoop(self):
# This function starts an endlos running thread through the gui
self.root.mainloop()
def __quit(self):
# close everything
self.root.quit()
def mainLoop(self):
# This function starts an endlos running thread through the gui
self.root.mainloop()
# init gui
my_gui = my_gui()
# execute gui
my_gui.mainLoop()
我有两个问题:
1) 我想如果我调整gui的大小,那么滚动条总是在gui的末端,我调整画布的大小
2) 如果我调整GUI和画布的大小,则画布中的矩形应调整大小(例如,如果GUI和画布的新大小是旧大小的四倍,则矩形的新大小是旧大小的两倍)
我分别为第一个问题和第二个问题寻找解决方案
谢谢您的帮助。您可以使用以下示例,或者将其集成到您的课堂中。 您可以通过调用创建这样的帧
self.frame = ScrollableFrame(self.root)
self.frame.pack(fill=BOTH, expand=YES)
为您的框架创建如下类:
from Tkinter import *
class ScrollableFrame(Frame):
'''
Creates a scrollable frame
'''
def __init__(self, parent, *args, **kw):
'''
Constructor
'''
Frame.__init__(self, parent, *args, **kw)
# create a vertical scrollbar
vscrollbar = Scrollbar(self, orient = VERTICAL)
vscrollbar.pack(fill = Y, side = RIGHT, expand = FALSE)
# create a horizontal scrollbar
hscrollbar = Scrollbar(self, orient = HORIZONTAL)
hscrollbar.pack(fill = X, side = BOTTOM, expand = FALSE)
#Create a canvas object and associate the scrollbars with it
canvas = Canvas(self, bd = 0, highlightthickness = 0, yscrollcommand = vscrollbar.set, xscrollcommand = hscrollbar.set)
canvas.pack(side = LEFT, fill = BOTH, expand = TRUE)
#Associate scrollbars with canvas view
vscrollbar.config(command = canvas.yview)
hscrollbar.config(command = canvas.xview)
# set the view to 0,0 at initialization
canvas.xview_moveto(0)
canvas.yview_moveto(0)
# create an interior frame to be created inside the canvas
self.interior = interior = Frame(canvas)
interior_id = canvas.create_window(0, 0, window=interior,
anchor=NW)
# track changes to the canvas and frame width and sync them,
# also updating the scrollbar
def _configure_interior(event):
# update the scrollbars to match the size of the inner frame
size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
canvas.config(scrollregion='0 0 %s %s' % size)
if interior.winfo_reqwidth() != canvas.winfo_width():
# update the canvas's width to fit the inner frame
canvas.config(width = interior.winfo_reqwidth())
interior.bind('<Configure>', _configure_interior)
从Tkinter导入*
类ScrollableFrame(框架):
'''
创建可滚动的框架
'''
定义初始值(自、父、*args、**kw):
'''
建造师
'''
帧。\uuuuu初始化(自,父,*args,**kw)
#创建一个垂直滚动条
vscrollbar=滚动条(自,方向=垂直)
vscrollbar.pack(填充=Y,侧边=RIGHT,展开=FALSE)
#创建一个水平滚动条
hs滚动条=滚动条(自身,方向=水平)
hscrollbar.pack(填充=X,侧面=底部,展开=FALSE)
#创建画布对象并将滚动条与其关联
canvas=canvas(self,bd=0,highlightthickness=0,yscrollcommand=vscrollbar.set,xscrollcommand=hscrollbar.set)
canvas.pack(side=LEFT,fill=BOTH,expand=TRUE)
#将滚动条与画布视图关联
vscrollbar.config(命令=canvas.yview)
hscrollbar.config(命令=canvas.xview)
#初始化时将视图设置为0,0
canvas.xview_moveto(0)
canvas.yview_moveto(0)
#创建要在画布内部创建的内部框架
self.interior=内部=框架(画布)
内部=画布。创建窗口(0,0,窗口=内部,
锚点=西北)
#跟踪画布和帧宽度的更改并同步它们,
#同时更新滚动条
def_配置_内部(事件):
#更新滚动条以匹配内部框架的大小
大小=(interior.winfo_reqwidth(),interior.winfo_reqheight())
canvas.config(scrollregion='0%s%s'%size]
if interior.winfo_reqwidth()!=canvas.winfo_width():
#更新画布的宽度以适合内部框架
canvas.config(width=interior.winfo_reqwidth())
内部绑定(“”,\u配置\u内部)
您可以使用它来获得所需的结果。水平和垂直滚动都为此框架启用,滚动条位置可以使用“侧”字段设置。
关于问题的第二部分,请你进一步澄清
参考:Gonzo的答案
您可以使用以下方法将my frame集成到gui类中:
from Tkinter import *
class ScrollableFrame(Frame):
def __init__(self, parent, *args, **kw):
'''
Constructor
'''
Frame.__init__(self, parent, *args, **kw)
# create a vertical scrollbar
vscrollbar = Scrollbar(self, orient = VERTICAL)
vscrollbar.pack(fill = Y, side = RIGHT, expand = FALSE)
# create a horizontal scrollbar
hscrollbar = Scrollbar(self, orient = HORIZONTAL)
hscrollbar.pack(fill = X, side = BOTTOM, expand = FALSE)
#Create a canvas object and associate the scrollbars with it
self.canvas = Canvas(self, bd = 0, highlightthickness = 0, yscrollcommand = vscrollbar.set, xscrollcommand = hscrollbar.set)
self.canvas.pack(side = LEFT, fill = BOTH, expand = TRUE)
#Associate scrollbars with canvas view
vscrollbar.config(command = self.canvas.yview)
hscrollbar.config(command = self.canvas.xview)
# set the view to 0,0 at initialization
self.canvas.xview_moveto(0)
self.canvas.yview_moveto(0)
# create an interior frame to be created inside the canvas
self.interior = interior = Frame(self.canvas)
interior_id = self.canvas.create_window(0, 0, window=interior,
anchor=NW)
# track changes to the canvas and frame width and sync them,
# also updating the scrollbar
def _configure_interior(event):
# update the scrollbars to match the size of the inner frame
size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
self.canvas.config(scrollregion='0 0 %s %s' % size)
if interior.winfo_reqwidth() != self.canvas.winfo_width():
# update the canvas's width to fit the inner frame
self.canvas.config(width = interior.winfo_reqwidth())
interior.bind('<Configure>', _configure_interior)
class my_gui(Frame):
def __init__(self):
# main tk object
self.root = Tk()
# init Frame
Frame.__init__(self, self.root)
# create frame (gray window)
self.frame = ScrollableFrame(self.root)
self.frame.pack(fill=BOTH, expand=YES)
#self.__add_scroll_bars()
#self.__create_canvas()
self.__add_plot()
def __add_plot(self):
# create a rectangle
self.frame.canvas.create_polygon(10, 10, 10, 150, 200, 150, 200, 10, fill="gray", outline="black")
def mainLoop(self):
# This function starts an endlos running thread through the gui
self.root.mainloop()
def __quit(self):
# close everything
self.root.quit()
# init gui
my_gui = my_gui()
# execute gui
my_gui.mainLoop()
从Tkinter导入*
类ScrollableFrame(框架):
定义初始值(自、父、*args、**kw):
'''
建造师
'''
帧。\uuuuu初始化(自,父,*args,**kw)
#创建一个垂直滚动条
vscrollbar=滚动条(自,方向=垂直)
vscrollbar.pack(填充=Y,侧边=RIGHT,展开=FALSE)
#创建一个水平滚动条
hs滚动条=滚动条(自身,方向=水平)
hscrollbar.pack(填充=X,侧面=底部,展开=FALSE)
#创建画布对象并将滚动条与其关联
self.canvas=canvas(self,bd=0,highlightthickness=0,yscrollcommand=vscrollbar.set,xscrollcommand=hscrollbar.set)
self.canvas.pack(side=LEFT,fill=BOTH,expand=TRUE)
#将滚动条与画布视图关联
vscrollbar.config(命令=self.canvas.yview)
hscrollbar.config(命令=self.canvas.xview)
#初始化时将视图设置为0,0
self.canvas.xview\u moveto(0)
self.canvas.yview_moveto(0)
#创建要在画布内部创建的内部框架
self.interior=内部=框架(self.canvas)
interior\u id=self.canvas.create\u window(0,0,window=interior,
锚点=西北)
#跟踪画布和帧宽度的更改并同步它们,
#同时更新滚动条
def_配置_内部(事件):
#更新滚动条以匹配内部框架的大小
大小=(interior.winfo_reqwidth(),interior.winfo_reqheight())
self.canvas.config(scrollregion='0%s%s'%size]
if interior.winfo_reqwidth()!=self.canvas.winfo_width():
#更新画布的宽度以适合内部框架
self.canvas.config(width=interior.winfo_reqwidth())
内部绑定(“”,\u配置\u内部)
类my_gui(框架):
定义初始化(自):
#主tk对象
self.root=Tk()
#初始帧
Frame.\uuuu init\uuuu(self,self.root)
#创建框架(灰色窗口)
self.frame=ScrollableFrame(self.root)
self.frame.pack(fill=BOTH,expand=YES)
#self.\u添加\u滚动条()
#self.\u创建\u画布()
self.\u添加\u绘图()
定义添加绘图(自):
#创建一个矩形
self.frame.canvas.创建_多边形(10,10,10,150200150200,10,fill=“gray”,outline=“black”)
def主回路(自):
#此函数通过gui启动endlos运行线程
self.root.mainloop()
定义退出(自我):
#关闭一切
self.root.quit()
#初始化gui
my_gui=my_gui()
#执行gui
my_gui.mainLoop()
这基本上解决了您的第一个问题。至于第二个问题,您需要创建一个函数,以便在每次调整画布大小时重新渲染画布。在某种程度上类似于“配置”内部功能。这非常有效,可以用最小的可滚动画布大小获得我想要的。但仍然存在缺陷,当gui变得更大时,当它看起来如此,以至于无法滚动时,就有可能
from Tkinter import *
class ScrollableFrame(Frame):
def __init__(self, parent, minimal_canvas_size, *args, **kw):
'''
Constructor
'''
Frame.__init__(self, parent, *args, **kw)
self.minimal_canvas_size = minimal_canvas_size
# create a vertical scrollbar
vscrollbar = Scrollbar(self, orient = VERTICAL)
vscrollbar.pack(fill = Y, side = RIGHT, expand = FALSE)
# create a horizontal scrollbar
hscrollbar = Scrollbar(self, orient = HORIZONTAL)
hscrollbar.pack(fill = X, side = BOTTOM, expand = FALSE)
#Create a canvas object and associate the scrollbars with it
self.canvas = Canvas(self, bd = 0, highlightthickness = 0, yscrollcommand = vscrollbar.set, xscrollcommand = hscrollbar.set)
self.canvas.pack(side = LEFT, fill = BOTH, expand = TRUE)
#Associate scrollbars with canvas view
vscrollbar.config(command = self.canvas.yview)
hscrollbar.config(command = self.canvas.xview)
# set the view to 0,0 at initialization
self.canvas.xview_moveto(0)
self.canvas.yview_moveto(0)
self.canvas.config(scrollregion='0 0 %s %s' % self.minimal_canvas_size)
# create an interior frame to be created inside the canvas
self.interior = interior = Frame(self.canvas)
interior_id = self.canvas.create_window(0, 0, window=interior,
anchor=NW)
# track changes to the canvas and frame width and sync them,
# also updating the scrollbar
def _configure_interior(event):
# update the scrollbars to match the size of the inner frame
size = (max(interior.winfo_reqwidth(), self.minimal_canvas_size[0]), max(interior.winfo_reqheight(), self.minimal_canvas_size[1]))
self.canvas.config(scrollregion='0 0 %s %s' % size)
if interior.winfo_reqwidth() != self.canvas.winfo_width():
# update the canvas's width to fit the inner frame
self.canvas.config(width = interior.winfo_reqwidth())
interior.bind('<Configure>', _configure_interior)
class my_gui(Frame):
def __init__(self):
# main tk object
self.root = Tk()
# init Frame
Frame.__init__(self, self.root)
minimal_canvas_size = (500, 500)
# create frame (gray window)
self.frame = ScrollableFrame(self.root, minimal_canvas_size)
self.frame.pack(fill=BOTH, expand=YES)
self.__add_plot()
def __add_plot(self):
# create a rectangle
self.frame.canvas.create_polygon(10, 10, 10, 150, 200, 150, 200, 10, fill="gray", outline="black")
def mainLoop(self):
# This function starts an endlos running thread through the gui
self.root.mainloop()
def __quit(self):
# close everything
self.root.quit()
# init gui
my_gui = my_gui()
# execute gui
my_gui.mainLoop()