Tkinter - Text widget shrinks when Scrollbar is added
Question: I'm working on the GUI for a simple quiz app using Tkinter in Python 2.7. Thus
far, I have begun to set up my frame. I've put a scrollbar inside of a Text
widget named `results_txtbx` to scroll up and down a list noting the player's
performance on each question. I've been using `grid` since it's easier for me
to manage.

    
    
    from Tkinter import *
    
    class Q_and_A:
    
        def __init__(self, master):
            frame = Frame(master)
    
            Label(master).grid(row = 4)
    
            results_txtbx = Text(master)
            results_scrbr = Scrollbar(results_txtbx)
            results_scrbr.grid(sticky = NS + E)
    
            results_txtbx.config(width = 20, height = 4, wrap = NONE, yscrollcommand = results_scrbr.set)
            results_txtbx.grid(row = 3, column = 1, padx = 12, sticky = W)
    
    
    
    root = Tk()
    root.wm_title("Question and Answer")
    root.resizable(0, 0)
    
    app = Q_and_A(root)
    root.mainloop()
    

What happens is that when it runs, `results_txtbx` resizes to fit the
scrollbar. Is there any way to make it keep its original size using `grid`?


Answer: You don't want to use a text widget as the master for a scrollbar. Like any
other widget, if you pack or grid the scrollbar in the text widget, the text
widget will shrink or expand to fit the scrollbar. That is the crux of your
problem.

Instead, create a separate frame (which you're already doing), and use that
frame as the parent for both the text widget and the scrollbars. If you want
the appearance that the scrollbars are inside, set the borderwidth of the text
widget to zero, and then give the containing frame a small border.

As a final usability hint, I recommend _not_ making the window non-resizable.
Your users probably know better what size of window they want than you do.
Don't take that control away from your users.

Here's (roughly) how I would implement your code:

  * I would use `import Tkinter as tk` rather than `from Tkinter import *` since global imports are generally a bad idea. 
  * I would make `Q_and_A` a subclass of `tk.Frame` so that it can be treated as a widget. 
  * I would make the whole window resizable
  * I would separate widget creation from widget layout, so all my layout options are in one place. This makes it easier to write and maintain, IMO. 
  * As mentioned in my answer, I would put the text and scrollbar widgets inside a frame

Here's the final result:

    
    
    import Tkinter as tk
    
    class Q_and_A(tk.Frame):
        def __init__(self, master):
            tk.Frame.__init__(self, master, borderwidth=1, relief="sunken")
            self.label = tk.Label(self)
            self.results_txtbx = tk.Text(self, width=20, height=4, wrap="none",
                                         borderwidth=0, highlightthickness=0)
            self.results_scrbr = tk.Scrollbar(self, orient="vertical", 
                                              command=self.results_txtbx.yview)
            self.results_txtbx.configure(yscrollcommand=self.results_scrbr.set)
    
            self.label.grid(row=1, columnspan=2)
            self.results_scrbr.grid(row=0, column=1, sticky="ns")
            self.results_txtbx.grid(row=0, column=0, sticky="nsew")
            self.grid_rowconfigure(0, weight=1)
            self.grid_columnconfigure(0, weight=1)
    
    root = tk.Tk()
    root.wm_title("Question And Answer")
    
    app = Q_and_A(root)
    app.pack(side="top", fill="both", expand=True)
    root.mainloop()
    

