pythonpython-2.7tkintertix

How do you keep a widget in view while scrolling?


I am using Tix to automatically create a scroll bar as the content changes. I want to keep a button or two in the user's view while they scroll through the contents of the application. I haven't seen this question for Tkinter/Tix yet so I thought I'd ask.

The following code will create a sample of the problem where the button is at a fixed point in the window, and is subject to being scrolled.

from Tkinter import *
import Tix
class some_GUI:
    def __init__(self, root):
        sw= Tix.ScrolledWindow(root, scrollbar=Tix.AUTO)
        sw.pack(fill=Tix.BOTH, expand=1)
        frame1 = Frame(sw.window) 
        frame1.grid(row = 0, column = 1)
        frame2 = Frame(sw.window) 
        frame2.grid(row = 0, column = 2)
        def quit():
            root.quit()
        for i in range(0,300):
            label1 = Label(frame1, text = "foo")
            label1.grid(row = i, column = 0)
        button = Button(frame2, text  = "Quit", command = quit)
        button.pack()

root = Tix.Tk()
display = some_GUI(root)
root.mainloop()

I want the button(s) to be in "frame2" and centered vertically relative to the application's window. I tried using winfo_height/winfo_width to find the frame's height/ width to work with update, but these values didn't change with the addition of the labels and button.

Attempted/possible solutions:

EDIT: Although this isn't exactly what I had in mind, the following code works as per falsetru's suggestion in the comments:

from Tkinter import *
import Tix
class some_GUI:
    def __init__(self, root):
        def quit():
            root.quit()
        frame2 = Frame(root) 
        frame2.pack(side = RIGHT)
        button = Button(frame2, text  = "Quit", command = quit)
        button.pack()
        frame1 = Frame(root) 
        frame1.pack(side = LEFT)
        sw= Tix.ScrolledWindow(frame1, scrollbar=Tix.AUTO)
        sw.pack(fill=Tix.BOTH, expand=1)
        for widget in sw.subwidgets_all():
            print widget
        for i in range(0,300):
            label1 = Label(sw.window, text = "foo")
            label1.grid(row = i, column = i)
        print root.winfo_toplevel()
        for widget in sw.subwidgets_all():
            print widget



root = Tix.Tk()
display = some_GUI(root)
root.mainloop()

Solution

  • You can put the button out of ScrollWindows:

    import Tix
    from Tkinter import *
    
    
    def build_ui(root):
        sw = Tix.ScrolledWindow(root, scrollbar=Tix.AUTO)
        sw.pack(side=LEFT, fill=Tix.BOTH, expand=1)
        for i in range(300):
            label1 = Label(sw.window, text="foo")
            label1.grid(row=i, column=0)
        button = Button(root, text="Quit", command=root.quit)
        button.pack(side=RIGHT)
    
    
    root = Tix.Tk()
    build_ui(root)
    root.mainloop()