Search code examples
pythonpython-3.xtkintertkinter-text

Text widget expands wide without being asked to do that (other elements don't expand)


Building a GUI app, and I'm using Tkinter with ttkbootstrap.

Despite all problems and weird/inconsistent experience with Tkinter, I managed to build a functional GUI app, but I can't style it properly, because Tkinter behaves in unstable manner. The app runs ok, but my configurations and parameters for different objects apply or don't apply at random (but fixed for every element - there can be some element that simply ignores the configs that other elements don't ignore). I have literally two elements styled identically (in terms of placement; same params except grid row), but they behave differently on screen for no apparent reason, and I can't find a workaround to make them do what I want them to do (and what my current code kinda suggests they should do, but they don't).

Structure of GUI (not code):  
root window.  
Labelframe1: root, row=0, column=0, rowspan=1, columnspan=1  
Labelframe2: root, row=1, column=0, rowspan=1, columnspan=1  
Labelframe3: root, row=2, column=0, rowspan=1, columnspan=1 

All of the labelframes are styled identically. Labelframes 1 & 2 behave as expected, the third one does random junk I never asked it to do. Here is the screenshot:

Screenshot of app

The Log labelframe must be the same width as those above it. They all take 1 column and have columnspan of 1, they all span 1 row.

ConnectRFFEMasterLabelFrame.grid(row = 0, column = 0, rowspan = 1, columnspan = 1, sticky="nw", padx = (0,2))
ConfigRFFEMasterLabelFrame.grid(row = 1, column = 0, rowspan = 1, columnspan = 1, sticky="nw", padx = (0,2))
LogLabelFrame.grid(row = 2, column = 0, rowspan = 1, columnspan = 1, padx = (0,2), sticky="nw")

For whatever Tkinter logic reason, the presence of textbox expands the column, even tho it was never asked to do that. If I remove the textbox (don't use .grid() on it), the whole thing looks exactly as one would expect it to look (notice how the column got narrow - exactly what it is supposed and expected to be):

Screenshot of app

If I explicitly set the Text widget width, it also works as expected:

Screenshot of app

All I want to do is to have Text widget that would take full width of the labelframe within the first column of root window, just like labelframes above it do. But the Text() widget randomly explodes the first column even tho it's empty and none of my code asks for it:

LogLabelFrame = tb.Labelframe(root, text="Log")
LogLabelFrame.columnconfigure(0, weight = 1)
LogLabelFrame.rowconfigure(2, weight = 1)
#LogLabelFrame.columnconfigure(2, weight = 0)

global Logfield
Logfield = tb.Text(LogLabelFrame)
LogSaveButton = tb.Button(LogLabelFrame, text = "Save to file...", command = lambda: LogFieldAddLine("Log Test Line"))
LogClearButton = tb.Button(LogLabelFrame, text = "Clear Log", command = lambda: LogFieldClear())
LogSaveButton.grid(row = 0, column = 0, columnspan = 1, sticky = "news", pady = 1)
LogClearButton.grid(row = 1, column = 0, columnspan = 1, sticky = "news", pady = 1)
Logfield.grid(row = 2, column = 0, rowspan = 1, columnspan = 1, sticky="nw")
LogLabelFrame.grid(row = 2, column = 0, rowspan = 1, columnspan = 1, padx = (0,2), sticky="nw")

Is there a workaround to force text widget to take full width of its parent, but not expand it?

Unfortunately, internet search gave nothing, and in all examples and tutorials all the styling and placement tools like grid and pack work flawlessly (which in my experience was never the case, but that's probably a matter of my incompetence), and I couldn't find any materials which would discuss similar problems.

What am I overlooking? Can I somehow force element to have relative width of 100% of parent? (I haven't noticed any relative sizing tools at all, unlike, say, HTML/CSS)


Solution

  • Is there a workaround to force text widget to take full width of its parent, but not expand it?

    The solution is to set the size to the smallest value you think is appropriate, and then let it grow if there's more room. If you don't specify a size, the default width is going to be 80 characters. Set the width smaller if you want the widget to start out smaller.

    Since you're using grid, you may need to also do the following:

    • you use sticky="nsew" to get the widget to fill all space allocated to it
    • you configure the row and column that the widget is in to have a weight greater than zero. This will cause any extra space to be allocated to the place where the text widget is.