2012-03-18 62 views
2

因此,我有一个自定义小部件,它从框架继承而来,并包含画布和滚动条,还有一个自定义小部件也从我想要动态添加到画布的框架继承,根据需要调整该区域的大小。这里是我的代码:动态更改Tkinter中画布的滚动区域

class MessageItem(Frame): 
"""A message to be contained inside a scrollableContainer""" 

def __init__(self, message, **kwds): 
    Frame.__init__(self, **kwds) 
    self.text = Label(self, text = message) 
    self.text.grid(column = 0, row = 0, sticky = N+S+E+W) 

class scrollableContainer(Frame): 
"""A scrollable container that can contain a number of messages""" 

def initContents(self): 
    """Initializes a scrollbar, and a canvas that will contain all the items""" 

    #the canvas that will contain all our items 
    self.canv = Canvas(self) 
    self.canv.grid(column = 0, row = 0, sticky = N+S+W) 
    #force Tkinter to draw the canvas 
    self.canv.update_idletasks() 
    #use the values from the canvas being drawn to determine the size of the scroll region 
    #note that currently, since the canvas contains nothing, the scroll region will be the same as 
    #the size of the canvas 
    geometry = self.canv.winfo_geometry() 
    xsize, ysize, xpos, ypos = parse_geometry_string(geometry) 
    self.canv['scrollregion'] = (0, 0, xsize, ysize) 

    #the scrollbar for that canvas 
    self.vscroll = Scrollbar(self, orient = VERTICAL, command = self.canv.yview) 
    self.vscroll.grid(column = 1, row = 0, sticky = N+S+E) 

    self.canv["yscrollcommand"] = self.vscroll.set 

def __init__(self, **kwds): 
    Frame.__init__(self, **kwds) 

    #initialize the widget's contents 
    self.grid(sticky = N+S+E+W) 
    self.pack() 
    self.initContents() 

    #initialize the list of contents so we can append to it 
    self.contents = [] 

def addMessage(self, message): 
    #Add the message to the list of contents 
    self.contents.append(MessageItem(message)) 
    #Add the message to the grid 
    self.contents[(len(self.contents) - 1)].grid(column = 0, row = (len(self.contents) - 1)) 
    #set the new scrollable region for the canvas 
    scrollregionlist = self.canv['scrollregion'].split() 
    oldRegion = int(scrollregionlist[3]) 
    newRegion = oldRegion + parse_geometry_string(self.contents[ 
     (len(self.contents) - 1)].winfo_geometry())[3] 
    self.canv['scrollregion'] = (int(scrollregionlist[0]), int(scrollregionlist[1]), 
     int(scrollregionlist[2]), newRegion) 

我遇到的问题是,self.canv [“scrollregion”]似乎外面消失初始化的。在方法addMessage方法,在该行:

scrollregionlist = self.canv['scrollregion'].split() 

上self.canv的scrollregion属性返回一个空字符串,我可以通过在该行之前把一个

print self.canv['scrollregion'] 

立即核实

+0

我无法运行你的代码,因为我不知道parse_geometry_string被定义在那里。我很好奇你的问题,我想运行它自己。 – 2012-03-21 04:11:07

回答

1

你确定一个Text小工具在这里是不够的吗?

反正

from Tkinter import * 


class MessageItem(Frame): 
    """A message to be contained inside a scrollableContainer""" 

    def __init__(self, master, message, **kwds): 
     Frame.__init__(self, master, **kwds) 
     self.grid_rowconfigure(0, weight=1) 
     self.grid_columnconfigure(0, weight=1) 
     self.text = Label(self, text=message, anchor='w', bg='gold') 
     self.text.grid(row=0, column=0, sticky='nsew') 

class scrollableContainer(Frame): 
    """A scrollable container that can contain a number of messages""" 

    def __init__(self, master, **kwargs): 
     Frame.__init__(self, master, **kwargs) #holds canvas & scrollbars 
     self.grid_rowconfigure(0, weight=1) 
     self.grid_columnconfigure(0, weight=1) 

     self.canv = Canvas(self, bd=0, highlightthickness=0) 
     self.hScroll = Scrollbar(self, orient='horizontal', 
           command=self.canv.xview) 
     self.hScroll.grid(row=1, column=0, sticky='we') 
     self.vScroll = Scrollbar(self, orient='vertical', 
           command=self.canv.yview) 
     self.vScroll.grid(row=0, column=1, sticky='ns') 
     self.canv.grid(row=0, column=0, sticky='nsew')   
     self.canv.configure(xscrollcommand=self.hScroll.set, 
          yscrollcommand=self.vScroll.set) 

     self.frm = Frame(self.canv, bd=2, bg='green') #holds messages 
     self.frm.grid_columnconfigure(0, weight=1) 

     self.canv.create_window(0, 0, window=self.frm, anchor='nw', tags='inner') 

     self.messages = [] 
     for i in range(20): 
      m = MessageItem(self.frm, 'Something Profound', bd=2, bg='black') 
      m.grid(row=i, column=0, sticky='nsew', padx=2, pady=2) 
      self.messages.append(m) 

     self.update_layout()   
     self.canv.bind('<Configure>', self.on_configure) 

    def update_layout(self): 
     self.frm.update_idletasks() 
     self.canv.configure(scrollregion=self.canv.bbox('all')) 
     self.canv.yview('moveto','1.0') 
     self.size = self.frm.grid_size() 

    def on_configure(self, event): 
     w,h = event.width, event.height 
     natural = self.frm.winfo_reqwidth() 
     self.canv.itemconfigure('inner', width= w if w>natural else natural) 
     self.canv.configure(scrollregion=self.canv.bbox('all')) 

    def add_message(self, message): 
     m = MessageItem(self.frm, message, bd=2, bg='red') 
     m.grid(row=self.size[1], column=0, padx=2, pady=2, sticky='we') 
     self.messages.append(m) 
     self.update_layout() 


root = Tk() 
root.grid_rowconfigure(0, weight=1) 
root.grid_columnconfigure(0, weight=1) 
sc = scrollableContainer(root, bd=2, bg='black') 
sc.grid(row=0, column=0, sticky='nsew') 

def new_message(): 
    test = 'Something Profane' 
    sc.add_message(test) 

b = Button(root, text='New Message', command=new_message) 
b.grid(row=1, column=0, sticky='we') 

root.mainloop()