I, too, am a big fan of The Old Way:
import Tkinter as tk root = tk.Tk() root.tk.eval(""" package require Tk frame .f canvas .f.c -bg red -borderwidth 0 -highlightthickness 0 -yscrollcommand {.f.vert set} scrollbar .f.vert -orient vertical -command {.f.c yview} pack .f.vert -side right -fill y -expand 0 pack .f.c -side left -fill both -expand 1 frame .f.inner -bg blue .f.c create window 0 0 -anchor nw -window .f.inner -tags {frame} bind .f.c <Configure> { .f.c itemconfigure "frame" -width [ winfo width .f.c ] .f.c config -scrollregion [.f.c bbox all] } set bg [.f.inner cget -bg] grid columnconfigure .f.inner 2 -weight 1 for {set row 1} {$row < 20} {incr row} { set w .f.inner.rb$row set e1 .f.inner.e1$row set e2 .f.inner.e2$row set e3 .f.inner.e3$row radiobutton $w -text "" -variable active -value $row -bg $bg entry $e1 -bg "white" entry $e2 -bg "white" entry $e3 -bg "white" grid $w -row $row -column 0 -pady 2 grid $e1 -row $row -column 1 -sticky ew -pady 2 grid $e2 -row $row -column 2 -sticky ew -pady 2 grid $e3 -row $row -column 3 -sticky ew -pady 2 } set active 1 pack .f -side top -fill both -expand 1 """) selection = lambda: int(root.tk.eval("expr {$active}")) val = lambda r,c: root.tk.eval(".f.inner.e%s%s get" % (r, c)) ;D On Wed, Jul 3, 2013 at 8:41 AM, Bob Greschke <b...@passcal.nmt.edu> wrote: > 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.oak...@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 <b...@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@python.org > >> http://mail.python.org/mailman/listinfo/tkinter-discuss > > > > _______________________________________________ > Tkinter-discuss mailing list > Tkinter-discuss@python.org > http://mail.python.org/mailman/listinfo/tkinter-discuss >
_______________________________________________ Tkinter-discuss mailing list Tkinter-discuss@python.org http://mail.python.org/mailman/listinfo/tkinter-discuss