sidnical
sidnical

Reputation: 459

Python3.5 -configure a single cell to expand instead of the entire row or column

Picture a 4x4 grid in a tkinter window. I want to expand the cell at row 2, column 2 but not everything else on row 2 or column 2. Im designing a text window with selectable options on the left side in rows 1-15. Making row 2 with weight 1 and column 2 with weight 1 allows my Text widget to expand but so does everything else in row 2 and column 2. Any way around this?

from tkinter import *

root = Tk()


lbl1 = Label(root, text="label1")
lbl1.grid(row=0, column=1)

lbl2 = Label(root, text="label2")
lbl2.grid(row=1, column=0)

lbl3 = Label(root, text="label3")
lbl3.grid(row=3, column=0)

lbl4 = Label(root, text="label4")
lbl4.grid(row=5, column=0)

txt = Text(root, state='disabled', bg='#E8E8E8')
txt.grid(row=1, column=1, padx=10, pady=10, sticky="NSEW", columnspan=2,      rowspan=2)


root.rowconfigure(2, weight=1)
root.columnconfigure(2, weight=1)

root.mainloop()

Example 2:

from tkinter import *

root = Tk()
frame1 = Frame(root)
frame1.grid(row=0, column=1)
frame2 = Frame(root)
frame2.grid(row=1, column=0)
frame3 = Frame(root)
frame3.grid(row=1, column=1, rowspan=2, columnspan=2)


lbl1 = Label(frame1, text="label1")
lbl2 = Label(frame2, text="label2")
lbl3 = Label(frame2, text="label3")
lbl4 = Label(frame2, text="label4")

lbl1.grid(row=0, column=1, sticky=N)
lbl2.grid(row=3, column=0, sticky=N)
lbl3.grid(row=5, column=0, sticky=N)
lbl4.grid(row=7, column=0, sticky=N)

txt = Text(frame3, state='disabled', bg='#E8E8E8')
txt.grid(row=0, column=0, padx=10, pady=10, sticky="NSEW", columnspan=2, rowspan=2)


root.rowconfigure(2, weight=1)
root.columnconfigure(2, weight=1)
frame3.rowconfigure(0, weight=1)
frame3.columnconfigure(0, weight=1)
root.mainloop()

Example 2 has everything in the position I want it in but the Text widget does not expand. Is it possible to set a frame to expand when using grid?

Upvotes: 1

Views: 1385

Answers (3)

sidnical
sidnical

Reputation: 459

With the information everyone has provided I was able to come up with a solution. I left the Text widget on the main window instead of in a frame and put my labels/tools in frames. Basically using the fact that a frame will not expand to lock down the labels. Now when the window is expanded only the widget grows.

from tkinter import *

root = Tk()
frame1 = Frame(root)
frame1.grid(row=0, column=1)
frame2 = Frame(root)
frame2.grid(row=1, column=0)


lbl1 = Label(frame1, text="label1")
lbl2 = Label(frame2, text="label2")
lbl3 = Label(frame2, text="label3")
lbl4 = Label(frame2, text="label4")

lbl1.grid(row=0, column=1, sticky=N)
lbl2.grid(row=3, column=0, sticky=N)
lbl3.grid(row=5, column=0, sticky=N)
lbl4.grid(row=7, column=0, sticky=N)

txt = Text(root, state='disabled', bg='#E8E8E8')
txt.grid(row=1, column=1, padx=10, pady=10, sticky="NSEW", columnspan=2, rowspan=2)


root.rowconfigure(2, weight=1)
root.columnconfigure(2, weight=1)
root.mainloop()

Thanks for all the help.

Upvotes: 0

Bryan Oakley
Bryan Oakley

Reputation: 386285

Your question asks about a 4x4 grid, but your example shows only two columns. That makes it hard to understand what you want. In the comments you say you simply want the text area of the example to grow and shrink and all the labels together, so that's what I'll address.

The simplest solution is to have an extra row and column to the right and below the text area. Have the text widget span into those areas, and give those areas a weight of 1. That means that, as the window changes size, any extra space is allocated to areas not occupied by buttons.

pro tip: I find layout problems much easier to visualize and solve when all of the layout code is together.

It would look something like this:

lbl1.grid(row=0, column=1)
lbl2.grid(row=1, column=0)
lbl3.grid(row=2, column=0)
lbl4.grid(row=3, column=0)
txt.grid(row=1, column=1, padx=10, pady=10, sticky="NSEW", columnspan=2, rowspan=4)

root.rowconfigure(4, weight=1)
root.columnconfigure(2, weight=1)

I think your layout problems might be better solved by using pack instead of grid for part of the layout. For example, you might start with three areas: a toolbar, a side panel, and then main area with the text widget:

toolbar = Frame(root, ...)
side = Frame(root, ...)
main = Frame(root, ...)

toolbar.pack(side="top", fill="x")
side.pack(side="left", fill="y")
main.pack(side="right", fill="both", expand=True)

With that you now have three relatively independent areas. You can use pack or grid in each of these frames independently, making it much easier to keep track of rows and columns.

Upvotes: 2

Delioth
Delioth

Reputation: 1554

One way around it would be to make your grid twice as large, setting the things you want to be expandable to span two columns/rows.

I.e. you use exclusively odd numbered rows/columns for griding things ([1,1][1,3],[3,1][3,3]...) and you set even-numbered rows/columns to have weight. Anything you want to expand in one or both directions gets a columnspan or rowspan of 2, pushing it into a row/column which may expand as needed.

Upvotes: 1

Related Questions