[英]resizeable scrollable canvas with tkinter
這是我的一個非常簡單的 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)
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和畫布的新大小是舊大小的四倍,則矩形的新大小是舊大小的兩倍) .
我分別為第一個問題和第二個問題尋找解決方案。
感謝幫助。
您可以使用以下方式將我的框架集成到您的 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()
這應該基本上解決你的第一個問題。 至於第二個問題,您需要創建一個函數來在每次調整畫布大小時重新渲染畫布。 以類似於 _configure_interior 函數的方式。
您可以使用以下示例,或將其集成到您的班級中。 您可以通過調用創建這樣的框架。
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)
您可以使用它來獲得您想要的結果。 此框架的水平和垂直滾動均啟用,滾動條位置可以使用“側”字段設置。 對於您問題的第二部分,您能否進一步闡明。
參考:Gonzo 的答案Python Tkinter 滾動條框架
這非常有效,以最小的可滾動畫布尺寸獲得我想要的東西。 但是仍然存在錯誤,當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()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.