Legorooj
Legorooj

Reputation: 2757

tkinter resize window without scrollbar disappearing

I have been coding an application which is pretty much a fancy text editor, and I have been getting problems with resizing the widgets inside it. My goal is for it to look a bit like IDLE with a horizontal scrollbar as well.

from tkinter import *
from tkinter import ttk

root = Tk()

width = preset frame width in relation to root
hieght = preset frame height in relation to root

frame = ttk.Frame(master=root, width=width, height=height)
frame.grid()
frame.grid_propagate(False)

vbar = ttk.Scrollbar(root, orient=VERTICAL)
hbar = ttk.Scrollbar(root, orient=HORIZONTAL)
vbar.grid(row=0, column=1, sticky=N S)
hbar.grid(row=1, column=0, sticky=E W)

text_widget = Text(frame, width=189, height=47, wrap=NONE, undo=True, yscrollcommand=vbar.set, xscrollcommand=hbar.set)
text_widget.grid()

vbar.config(command=text_widget.yview)
hbar.config(command=text_widget.xview)

I am using python 3.7, windows 10 and PyCharm. If you find a duplicate of this question, please comment and let me check it out before marking as a duplicate and or closing, for i have yet to find an answer. it works, just resizing is the issue. it should behave a bit like windows notepad with word wrap off. Editor in split-screen

enter image description here

Upvotes: 0

Views: 1900

Answers (1)

Ethan Field
Ethan Field

Reputation: 4730

This is a relatively simple problem to solve.

If you wished to continue creating the program using the Grid geometry manager, you will need to familiarise yourself with the Grid.rowconfigure() and Grid.columnconfigure() functions.

These allow you to set the configuration options for the Grid geometry manager within the confines of a container widget. Specifically, the attribute we care about is weight. As explained here:

Every column and row has a "weight" grid option associated with it, which tells it how much it should grow if there is extra room in the master to fill. By default, the weight of each column or row is 0, meaning don't expand to fill space.

For the user interface to resize then, we'll need to give a positive weight to the columns we'd like to expand. This is done using the "columnconfigure" and "rowconfigure" methods of grid. If two columns have the same weight, they'll expand at the same rate; if one has a weight of 1, another of 3, the latter one will expand three pixels for every one pixel added to the first.

(emphasis mine)

So, in this case we need to make a few changes. Firstly, we need to add sticky = "NESW" to both the frame.grid() and text_widget.grid() calls, otherwise the Text widget won't expand with the scrollbars. Secondly, we need to add the below snippet to the program:

Grid.columnconfigure(root, 0, weight=1)
Grid.rowconfigure(root, 0, weight=1)

Grid.columnconfigure(frame, 0, weight=1)
Grid.rowconfigure(frame, 0, weight=1)

This ends up with the below program (after making some changes so I can actually run the provided example):

from tkinter import *
from tkinter import ttk

root = Tk()

frame = ttk.Frame(master=root)
frame.grid(sticky="NSEW")

vbar = ttk.Scrollbar(root, orient=VERTICAL)
hbar = ttk.Scrollbar(root, orient=HORIZONTAL)
vbar.grid(row=0, column=1, sticky="NS")
hbar.grid(row=1, column=0, sticky="EW")

text_widget = Text(frame, wrap=NONE, undo=True, yscrollcommand=vbar.set, xscrollcommand=hbar.set)
text_widget.grid(sticky="NSEW")

vbar.config(command=text_widget.yview)
hbar.config(command=text_widget.xview)

Grid.columnconfigure(root, 0, weight=1)
Grid.rowconfigure(root, 0, weight=1)

Grid.columnconfigure(frame, 0, weight=1)
Grid.rowconfigure(frame, 0, weight=1)

As a side note, it would be very simple to rebuild this program using the Pack geometry manager which is (subjectively) more intelligent when it comes to resizing widgets:

from tkinter import *
from tkinter import ttk

root = Tk()

frame = ttk.Frame(master=root)
frame.pack(expand=True, fill="both")

vbar = ttk.Scrollbar(frame, orient=VERTICAL)
hbar = ttk.Scrollbar(root, orient=HORIZONTAL)
vbar.pack(side="right", fill="y")
root.update()
hbar.pack(side="bottom", fill="x", padx=vbar.winfo_width())

text_widget = Text(frame, wrap=NONE, undo=True, yscrollcommand=vbar.set, xscrollcommand=hbar.set)
text_widget.pack(expand=True, fill="both")

vbar.config(command=text_widget.yview)
hbar.config(command=text_widget.xview)

Upvotes: 1

Related Questions