2012-03-18 72 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」]はのinitの外に消えて表示されます。そしてaddMessageメソッドでは、行に:

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

self.canv上scrollregionプロパティは、私はすぐにその行の前

+0

parse_geometry_stringが定義されている場所、私は知らないので、私はあなたのコードを実行することはできません..私はあなたの問題についての興味、私はそれを自分自身を実行したいと思います。 –

答えて

1

print self.canv['scrollregion'] 

を置くことによって確認することができ、空の文字列を返しますテキストウィジェットでは十分ではないでしょうか?とにかく

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() 
関連する問題