[Tkinter-discuss] Getting an Entry field to stretch

Bob Greschke bob at passcal.nmt.edu
Wed Jul 3 17:41:39 CEST 2013


You're as smart as ever! :)  This is nice.

Yeah, I'm not a very object-oriented kinda guy, which is coming in REAL handy trying to learn iOS programming where just about every character you type in the source code is an object.  My brain is too used to thinking The Old Way.

Thanks!

Bob


On 2013-07-02, at 15:41, Bryan Oakley <bryan.oakley at gmail.com> wrote:

> This problem requires that you do two things:
> 
> a) cause the width of the inner frame to resize when the canvas resizes
> b) make sure the widgets inside the inner frame resize when the inner
> frame resizes.
> 
> For a), you need to do a binding on the <Configure> event of the
> canvas. In the callback for that binding, use the canvas's
> 'itemconfigure' method to change the width of the inner frame.
> 
> For b), the easiest is to use the grid geometry manager and do away
> with all of the inner frames. Then all you need to do is configure the
> inner frame such that the appropriate column grows and shrinks. Of
> course, you can use the inner frames if you really want to. In that
> case you wouldn't use grid, you could use pack, and as long as the
> inner frames were all packed identically with one entry being told to
> expand, it will all work just fine.
> 
> It's hard to retrofit some of that into the code you posted. I'll post
> some code to illustrate how I would do it. I switched up the style of
> the app as a whole to something more object-oriented, and I did away
> with the global imports. I think these two changes make for a better
> way to write Tkinter apps.
> 
> import Tkinter as tk
> 
> class Example(tk.Frame):
>    def __init__(self, *args, **kwargs):
>        tk.Frame.__init__(self, *args, **kwargs)
> 
>        self.activeVar = tk.StringVar()
>        self.activeVar.set(1)
> 
>        self.canvas = tk.Canvas(self,
>                                background="red",
>                                borderwidth=0,
>                                highlightthickness=0)
>        self.vsb = tk.Scrollbar(self, orient="vertical",
> command=self.canvas.yview)
>        self.canvas.config(yscrollcommand=self.vsb.set)
>        self.vsb.pack(side="right", fill="y", expand=False)
>        self.canvas.pack(side="left", fill="both", expand=True)
> 
>        self.inner_frame = tk.Frame(self, background="blue")
>        self.canvas.create_window(0,0,
>                                  anchor="nw",
>                                  window=self.inner_frame,
>                                  tags=("frame",))
>        self.canvas.bind("<Configure>", self._on_canvas_resize)
>        self._add_widgets(20)
> 
>    def _on_canvas_resize(self, event=None):
>        width = self.canvas.winfo_width()
>        self.canvas.itemconfigure("frame", width=width)
>        self.canvas.config(scrollregion=self.canvas.bbox("all"))
> 
>    def _add_widgets(self, count):
>        bg = self.inner_frame.cget('background')
>        self.inner_frame.grid_columnconfigure(2, weight=1)
> 
>        for row in xrange(1, count):
>            lrb = tk.Radiobutton(self.inner_frame, text="",
>                                 variable = self.activeVar,
>                                 value=str(row),
>                                 background=bg)
>            lent1 = tk.Entry(self.inner_frame,  bg = "white")
>            lent2 = tk.Entry(self.inner_frame,  bg = "white")
>            lent3 = tk.Entry(self.inner_frame,  bg = "white")
> 
>            lrb.grid(row=row, column=0, pady=2)
>            lent1.grid(row=row, column=1, sticky='ew', pady=2)
>            lent2.grid(row=row, column=2, sticky='ew', pady=2)
>            lent3.grid(row=row, column=3, sticky='ew', pady=2)
> 
> 
> if __name__ == "__main__":
>    root = tk.Tk()
>    Example(root).pack(side="top", fill="both", expand=True)
>    root.mainloop()
> 
> On Tue, Jul 2, 2013 at 3:59 PM, Bob Greschke <bob at passcal.nmt.edu> wrote:
>> This is what I want to do...almost:
>> 
>> -----
>> #! /usr/bin/env python
>> 
>> from Tkinter import *
>> 
>> Root = Tk()
>> 
>> RowActiveVar = StringVar()
>> 
>> LastWidth = 0
>> Count = 0
>> def iChanged(e = None):
>>    global LastWidth
>>    global Count
>>    Count += 1
>>    Geom = Root.geometry()
>>    Width = int(Geom[:Geom.index("x")])
>>    if Width == LastWidth:
>>        return
>> #    Root.geometry("%d%s"%((Width+ScrollWidth+2), Geom[Geom.index("x"):]))
>>    LastWidth = Width+ScrollWidth+2
>>    return
>> 
>> RowSub = Frame(Root, bg = "blue")
>> RowCan = Canvas(RowSub, bg = "red")
>> RowCan.pack(side = LEFT, expand = YES, fill = BOTH)
>> Scroll = Scrollbar(RowSub, orient = VERTICAL, command = RowCan.yview, \
>>        width = 15)
>> Scroll.pack(side = RIGHT, fill = Y)
>> ScrollWidth = int(Scroll.cget("width"))+int(Scroll.cget("bd"))*2+ \
>>        int(Scroll.cget("highlightthickness"))*2
>> RowCan.configure(yscrollcommand = Scroll.set)
>> RowSub.pack(side = TOP, expand = YES, fill = BOTH)
>> 
>> Y = 0
>> for I in xrange(1, 20):
>>    SSub = Frame()
>>    LRb = Radiobutton(SSub, text = "", variable = RowActiveVar, \
>>            value = str(I), bg = Frame().cget("bg"))
>>    LRb.pack(side = LEFT)
>>    LEnt = Entry(SSub, width = 15, bg = "white")
>>    LEnt.pack(side = LEFT)
>> # This one...
>>    LEnt = Entry(SSub, width = 40, bg = "white")
>>    LEnt.pack(side = LEFT, expand = YES, fill = X)
>>    LEnt = Entry(SSub, width = 10, bg = "white")
>>    LEnt.pack(side = LEFT)
>>    SSub.pack(expand = YES, fill = X)
>>    RowCan.create_window(0, Y, anchor = "nw", window = SSub)
>>    RowCan.update()
>>    L,T,R,B = RowCan.bbox(ALL)
>>    Y = B
>> RowCan.configure(scrollregion = (0, 0, R, B))
>> Geom = Root.geometry()
>> LastWidth = R+ScrollWidth+2
>> Root.geometry("%d%s"%(LastWidth, Geom[Geom.index("x"):]))
>> Root.bind("<Configure>", iChanged)
>> 
>> Root.mainloop()
>> -----
>> 
>> I'd like the center column of Entry fields to get longer as the window width is changed.  I have a static non-scrollbar version of this that works fine (Entry fields in a Frame that is packed TOP into another Frame -- everyone set to expand and fill as needed), but throwing the Canvas and the scrolling in there seems to be a problem.  I have another version that uses a Text() to hold all of the rows, but I can't get that to work either.  The iChanged() stuff really doesn't do anything at this point.  I was thinking that might be where a solution goes.  Can it be done?
>> 
>> Thanks!
>> 
>> Bob
>> 
>> _______________________________________________
>> Tkinter-discuss mailing list
>> Tkinter-discuss at python.org
>> http://mail.python.org/mailman/listinfo/tkinter-discuss
> 



More information about the Tkinter-discuss mailing list