0
votes

I have a master frame with five columns, which I want to stay at same width all the time, regardless of how window is resized. There are three rows, the bottom being buttons.

The problem is when I added a Text widget to the larger Frame 3, it stretches out the column width in colums 2, 3, 4 to wider than columns 0 & 1.

I've tried to deal with this by making sure I set all the column weights equal, but this only helps keep the columns maintain their relative size while resizing the master window. It doesn't force the columns to be the same with when the master is instantiated.

I tried using a self.columnconfigure(c,minsize=100) and this makes the columns look even width when I instantiate the object. But if I resize the window bigger, the three righthand colums expand faster than the left two columns, despite all being assigned the same weight! And if I make the window two narrow, in order to maintain the 'minsize' of width, columns aren't visible on the far right. So this isn't a solution.

screenshot of my issue

def __init__(self, master=None):
    Frame.__init__(self, master)

    self.master.rowconfigure(0, weight=1) 
    self.master.columnconfigure(0, weight=1)
    self.grid(sticky=W+E+N+S)


    """ Establish grids, columns for the master Frame widget """
    for c in range(5):
        # 0,1,2,3,4
        self.columnconfigure(c, weight=1)

    self.rowconfigure(0, weight = 1)
    self.rowconfigure(1, weight = 1)
    self.rowconfigure(2, weight = 0)


    """ Generate Buttons """
    self.button = dict()
    for r in range(5):
        self.button[r]=Button(self)
        self.button[r].grid(column=r, row=2, sticky=N+S+E+W)

    self.button[0].config(command=self.b0, text="red")
    self.button[1].config(command=self.b1, text="blue")
    self.button[2].config(command=self.b2, text="green")
    self.button[3].config(command=self.b3, text="black")
    self.button[4].config(command=self.b4, text = "open")

continued

    """ Frame 1 """
    self.f1 = Frame(self, bg="red")
    self.f1.grid(row=0, column=0, columnspan=2,rowspan=1, sticky=N+S+W+E)

    self.f1.bind("<Button-1>", self.f1_button)

    """didn't help"""
    #self.f1.columnconfigure(0, weight=1)
    #self.f1.columnconfigure(1, weight=1)

    self.label_1_var = StringVar()
    self.label_1_var.set("frame 1")
    self.label_1 = Label(self.f1, textvariable=self.label_1_var)
    self.label_1.grid(row=1, column=1)


    """ Frame 2 """
    self.f2 = Frame(self, bg="blue")
    self.f2.grid(row=1, column=0, columnspan=2,rowspan=1, sticky=N+S+E+W)

    self.f2.bind("<Button-1>", self.f2_button)

    """didn't help"""
    #self.f2.columnconfigure(0, weight=1)
    #self.f2.columnconfigure(1, weight=1)

    self.label_2_var = StringVar()
    self.label_2_var.set("frame 2")
    self.label_2 = Label(self.f2, textvariable = self.label_2_var)
    self.label_2.grid(row=1, column=1)

continued

""" frame 3 """
    self.f3 = Frame(self, bg="green")
    self.f3.grid(row=0, column=2, columnspan=3, rowspan = 2, sticky=N+S+E+W)
    self.f3.rowconfigure(0,weight=1)
    self.f3.rowconfigure(1,weight=0)
    self.f3.columnconfigure(0, weight=1)        

    """list some files to try"""
    files = glob.glob("*")
    default_display =""
    for fn in files:
        default_display += fn + "\n"

    """ Text widget """
    self.f3_text = Text(self.f3)
    self.f3_text.insert(END, default_display)
    self.f3_text.grid(column=0, row=0,sticky=N+S+E+W)

    """ Text scrollbar """
    self.sb = Scrollbar(self.f3)
    self.sb.grid(column=1, row=0, sticky=N+S+E+W)
    self.f3_text.config(yscrollcommand=self.sb.set)
    self.sb.config(command=self.f3_text.yview)

    """ Entry Window """
    self.f3_entry = Entry(self.f3)
    self.f3_entry.grid(column=0, row=1, columnspan=2, sticky=N+S+E+W)
3

3 Answers

1
votes

A simple solution is to set the width and height of the widget to 1, and then rely on the grid options to stretch it to fill its container. Since it's natural size is smaller than the cell it is in, it won't cause the cell to grow.

0
votes

You want to set the width of the text widget:

text = Text(frame, width=20)

By default, the width is set to 80 characters. Note that this value isn't constant, so the widget is resized correctly.

-1
votes

Hint: "... regardless of the resize":

While it would be great to rely on behaviour / services of the most common public methods exposed from automated Tk-GUI-MVC-Visual Part, the real-world layout complexities may get us to a dead-end.

Try a hard-coded programmatic way to automatically ad-hoc re-calculate / re-construct the Tk-GUI-MVC-Visual Part from new, changed, internal values from the Tk-GUI-MVC-Controller Part:

 master.bind( '<Configure>', aResizeCallbackHANDLER( ) )  # MVC-Controller Part TRIGGER

 def aResizeCallbackHANDLER( self, anEvent ):             # Reactor:
     # inspect <anEvent>.{}                               # .bind()-bound actor
     # and     <anEvent>.widget.{}                        # details from
     # incl.   <anEvent>.widget.<Tree-sub-element>.{}     # Tk-GUI-MVC-Model Part
     #
     #         <anEvent>.widget      <-- system-assigned <widget>-instance
     #                  .height      on-{ <Configure> }
     #                  .width       on-{ <Configure> }
     #                  .serial      <-- system-assigned Integer
     #                  .time        <-- system-assigned Integer ( .inc each msec )
     # .
     # ..
     # ...
     # Act upon changes and enforce new, re-calculated values
     #                      into sub-ordinated geometry
     # ...
     #

This principle is robust and does not rely on any "hidden" inter-relations of Tk-GUI-MVC-elements.