0

Tkinter 'ScrolledText' widget changes size when I change font size. This problem also persists for 'Text' widget.

I resolved parent frame resizing with font size of Text widget by using '.grid_propagate(False)' as suggested in this post.

I have tried '.grid_propagate(False)' on Text widget also to no avail. Text widget remains same size only when using 'sticky=nsew' but that stretches Text widget to fill the parent frame. Is there any way to handle this problem?

import tkinter as tk
from tkinter.scrolledtext import ScrolledText
window = tk.Tk();
PW1 = tk.PanedWindow(master=window,orient='vertical',bg="#E0E0E0",bd=9)
PW1.pack(side='left',expand='True',fill='both')      
PW1.grid_propagate(False)              
PW1.grid_rowconfigure(0, weight=1)       
PW1.grid_columnconfigure(0, weight=1)
textField1 = ScrolledText(master=PW1,font=('Times New Roman',12))
textField1.grid(row=0, column=0, padx=5, pady=5,sticky='nsew')
window.mainloop()  
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
Raj
  • 23
  • 6

2 Answers2

1

A simple solution is to give the text widget an unnaturally small size (eg: 1x1), and let the containing window determine the actual size of the widget via the pack, place, or grid geometry manager options. As long as the requested size is smaller than the actual size, the user will never see it grow.

Technically the widget will still grow, but unless you've literally only given it a tiny spot in the GUI, the user will not see it grow because it's requested size will always be smaller than the actual size.

Here's an example, using your code as a starting point.

import tkinter as tk
from tkinter.scrolledtext import ScrolledText

window = tk.Tk();
window.geometry("400x400")

def set_font(size):
    textField1.configure(font=('Times new Roman', size))

f = tk.Frame(window)
f.pack(side="bottom", fill="x")
for size in (8, 12, 18, 24):
    b = tk.Button(f, text=size, width=2, command=lambda size=size: set_font(size))
    b.pack(side="left")


PW1 = tk.PanedWindow(master=window,orient='vertical',bg="#E0E0E0",bd=9)
PW1.pack(side='left',expand='True',fill='both')
PW1.grid_propagate(False)
PW1.grid_rowconfigure(0, weight=1)
PW1.grid_columnconfigure(0, weight=1)
textField1 = ScrolledText(master=PW1,font=('Times New Roman',12), width=1, height=1)
textField1.grid(row=0, column=0, padx=5, pady=5,sticky='nsew')

window.mainloop()

The other solution is to turn off geometry propagation in the widget that contains the text widget just as you have done, and then use that widget to control the size. No matter what size the text widget tries to be, it will be the containing widget that controls the actual size.

I have tried '.grid_propagate(False)' on Text widget also to no avail.

That is because grid_propagate affects how children affect the widget. Since your text widget doesn't have any children, the command has no effect.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • Thanks, but this solution works when Text widget is stretched. So I have to have child frame if I want to stack two widget horizontally, right? – Raj Aug 07 '19 at 06:13
  • @Raj: I don't understand your question. For this to work with geometry propagation, the text widget needs to be inside a child frame and configured to fill that frame. However, you can put that frame anywhere you want, and you don't have to stretch it. – Bryan Oakley Aug 07 '19 at 13:10
  • Thanks, that's what I was trying to ask "text widget has to fill the frame". – Raj Aug 07 '19 at 14:19
  • @Raj: just to be clear: it has to fill _a_ frame, but you can create a special frame specifically for the text widget, and which only contains the text widget. – Bryan Oakley Aug 07 '19 at 14:21
0

This is a difficult problem and I have never seen any usable documentation of how this works. There is, however, a hint in this thread: If the text changes the size of the the and widget changes the size

There was a great deal of trial and error and I finally got it to work with pack(). I was not successful with grid().

I do not understand exactly how you intend to use PanedWindow() so I'll provide an example which uses Frame():

import tkinter as tk
from tkinter.scrolledtext import ScrolledText

window = tk.Tk()

# Container will not expand when window gets bigger but will
# shrink as window gets smaller
container = tk.Frame(window, width=300, height=200, bg='tan')
container.pack()
container.pack_propagate(False)

# textField1 will not cause container size change
textField1 = ScrolledText(container,font=('Times New Roman',12))
textField1.pack(padx=5, pady=5)

# Changing font size for testing purposes
def change_font(event):
    textField1.config(font=('Times New Roman',24))
window.bind('<space>', change_font)

window.mainloop()
figbeam
  • 7,001
  • 2
  • 12
  • 18
  • _"I have never seen any usable documentation of how this works."_ - precisely how it works is documented in the canonical tcl/tk documentation for [grid](http://tcl.tk/man/tcl8.5/TkCmd/grid.htm#M32) and [pack](http://tcl.tk/man/tcl8.5/TkCmd/pack.htm#M26). They explain how the available space is used when laying out widgets. – Bryan Oakley Aug 05 '19 at 22:28