Tkinter grid fill empty space - python

I did search for a lot of examples before posting but still can't properly use the tkinter grid.
What I want:
my code:
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
b1 = ttk.Button(root, text='b1')
b1.grid(row=0, column=0, sticky=tk.W)
e1 = ttk.Entry(root)
e1.grid(row=0, column=1, sticky=tk.EW)
t = ttk.Treeview(root)
t.grid(row=1, column=0, sticky=tk.NSEW)
scroll = ttk.Scrollbar(root)
scroll.grid(row=1, column=1, sticky=tk.E+tk.NS)
scroll.configure(command=t.yview)
t.configure(yscrollcommand=scroll.set)
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=1)
root.rowconfigure(1, weight=1)
root.mainloop()

The quick and simple solution is to define the columnspan of the treeview. This will tell the treeview to spread across 2 columns and allow the entry field to sit next to your button.
On an unrelated note you can use strings for your sticky so you do not have to do things like tk.E+tk.NS. Instead simply use "nse" or whatever directions you need. Make sure thought you are doing them in order of "nsew".
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
b1 = ttk.Button(root, text='b1')
b1.grid(row=0, column=0, sticky="w")
e1 = ttk.Entry(root)
e1.grid(row=0, column=1, sticky="ew")
t = ttk.Treeview(root)
t.grid(row=1, column=0, columnspan=2, sticky="nsew") # columnspan=2 goes here.
scroll = ttk.Scrollbar(root)
scroll.grid(row=1, column=2, sticky="nse") # set this to column=2 so it sits in the correct spot.
scroll.configure(command=t.yview)
t.configure(yscrollcommand=scroll.set)
# root.columnconfigure(0, weight=1) Removing this line fixes the sizing issue with the entry field.
root.columnconfigure(1, weight=1)
root.rowconfigure(1, weight=1)
root.mainloop()
Results:
To fix your issue you mention in the comments you can delete root.columnconfigure(0, weight=1) to get the entry to expand properly.

Related

Tkinter: 2 buttons next to each other resize in width with window. How to?

The 2 buttons should take each of the half of the window, one on the left, one on the right. The height is fixed all time. With .grid() nor .place() I can come to that result. The red bar is the color of the frame where the buttons are placed on. The buttons resize in width with the window, but keep their constant height.
How to?
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, bg='red')
frame.pack(fill='both', expand=True)
button1 = tk.Button(frame, text="<<")
button2 = tk.Button(frame, text=">>")
button1.grid(row=0, column=0, sticky='nsew')
button2.grid(row=0, column=1, sticky='nsew')
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=1)
root.mainloop()
Thx.
In the mean time I got this:
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, bg='red',height=30)
frame.pack(fill='both')
button1 = tk.Button(frame, text="<<")
button2 = tk.Button(frame, text=">>")
button1.place(relwidth=0.5, relx=0, relheight=1)
button2.place(relwidth=0.5, relx=0.5, relheight=1)
root.mainloop()
Assuming that the buttons are the only widgets in the frame (ie: you are making a toolbar), I would use pack. grid will also work, but it requires one extra line of code.
Using pack
Here's a version with pack. Notice that the frame is packed along the top and fills the window in the "x" direction. The buttons each are instructed to expand (ie: receive extra, unused space) and to fill the space allocated to them in the "x" direction.
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, bg='red',height=30)
frame.pack(side="top", fill="x")
button1 = tk.Button(frame, text="<<")
button2 = tk.Button(frame, text=">>")
button1.pack(side="left", fill="x", expand=True)
button2.pack(side="right", fill="x", expand=True)
root.mainloop()
Using Grid
A version with grid is similar, but you must use columnconfigure to give a non-zero weight to the two columns:
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, bg='red',height=30)
frame.pack(side="top", fill="x")
button1 = tk.Button(frame, text="<<")
button2 = tk.Button(frame, text=">>")
button1.grid(row=0, column=0, sticky="ew")
button2.grid(row=0, column=1, sticky="ew")
frame.grid_columnconfigure((0, 1), weight=1)
root.mainloop()

Python Tkinter - frame weight problem using grid layout

root frame weight is correct when button btnOpen is not present (commented). Otherwise the weight of root and frLeft is about 1:1. Why button (or frame frButtons) makes a difference?
Here is the code:
from tkinter import *
root = Tk()
root.title("xxx")
root.geometry("500x400")
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=15)
root.columnconfigure(1, weight=10)
frLeft = Frame(root, bg="#808080")
frLeft.grid(row=0, column=0, sticky="NSEW")
frRight = Frame(root, bg="#FAF0F0")
frRight.grid(row=0, column=1, sticky="NSEW")
frRight.rowconfigure(0, weight=1)
frButtons = Frame(frRight, bg="red")
frButtons.grid(row=0, column=0, sticky="W", padx=10, pady=10)
btnOpen = Button(frButtons, command=open, text='Open', padx=2).grid(row=0, sticky="WS", padx=10)
root.mainloop()
Correct:
Not correct:

Python tkinter how to use grid sticky

import tkinter as tk
root = tk.Tk()
root.state('zoomed')
text1 = tk.Text(state=tk.DISABLED)
scroll = tk.Scrollbar(root, command=text1.yview)
text1.configure(yscrollcommand=scroll.set)
text1.grid(row=1, column=1, sticky='we')
scroll.grid(row=1, column=2, sticky="nse")
root.mainloop()
How do I make the Text box fill the X axis? (sticky='we' did not work for me)
import tkinter as tk
root = tk.Tk()
root.state('zoomed')
text1 = tk.Text(state=tk.DISABLED)
scroll = tk.Scrollbar(root, command=text1.yview)
text1.configure(yscrollcommand=scroll.set)
text1.grid(row=1, column=0,sticky='we')
scroll.grid(row=1, column=1, sticky="ns")
root.grid_columnconfigure(0, weight=1)
root.grid_columnconfigure(1, weight=0)
root.mainloop()
I've added the parameter weight to the columns in that grid, which basically is a relationship between the columns. Please see,
What does 'weight' do in tkinter? to get a more detailed answer.

Tkinter columnconfigure weight not adjusting

I am new to the Tkinter module. I only have experience with PyQt5. I am playing with a couple widgets in my Frame. They are three buttons, and I am trying to expand their size relative to the size of the window. To do this I am using w.columnconfigure(n, weight=1). This should spread the 3 buttons I have across the window Frame. This is the code I am running. I have tried with the w.columnconfigure before placing the widgets in the grid, and, as seen in the posted code, after the widgets are placed in the grid. I noticed no difference or functionality. Is there a convention? Anyway, appreciate any guidance!
def create_widgets(self):
""" Create three buttons that do nothing. """
self.bttn1 = Button(self, text="I do nothing")
self.bttn2 = Button(self)
self.bttn2.configure(text="Me too!")
self.bttn3 = Button(self)
self.bttn3["text"] = "Same here!"
self.bttnCt = Button(self)
self.bttnCt["text"] = "Total Clicks: 0"
self.bttnCt["command"] = self.update_count
self.bttn1.grid(row=0, column=0, sticky=W+E)
self.bttn2.grid(row=0, column=1, sticky=W+E)
self.bttn3.grid(row=0, column=2, sticky=W+E)
self.bttnCt.grid(row=1, column=1, sticky=W+E)
bttn_list = [self.bttn1, self.bttn2, self.bttn3, self.bttnCt]
for k, i in enumerate(bttn_list):
i.columnconfigure(k, weight=1)
#self.bttn1.columnconfigure(0, weight=1)
#self.bttn2.columnconfigure(1, weight=3)
#self.bttn3.columnconfigure(2, weight=1)
#self.bttnCt.columnconfigure(3, weight=1)
columnconfigure() or rowconfigure() functions are applied to the window or frame, of which the widget is a part of. Here you are applying it on the button itself. Apply it on on its parent basically.
Here is a small example.
import tkinter as tk
app = tk.Tk()
bttn1 = tk.Button(app, text="I do nothing")
bttn2 = tk.Button(app, text='Me too!')
bttn3 = tk.Button(app, text='Same here!')
bttnCt = tk.Button(app, text='Total Clicks: 0')
bttn1.grid(row=0, column=0, sticky="ew")
bttn2.grid(row=0, column=1, sticky="ew")
bttn3.grid(row=0, column=2, sticky="ew")
bttnCt.grid(row=1, column=1, sticky="ew")
bttn_list = [bttn1, bttn2, bttn3, bttnCt]
for i in range(len(bttn_list)):
app.columnconfigure(i, weight=1) ## Not the button, but the parent
app.mainloop()

Python Tkinter: Paned Window not sticking to top

Thanks for taking time to look at this. I've been struggling with this for almost a week and its driving me crazy.
I have a horizontal Paned Window which is supposed to stretch from the bottom of my toolbar to the bottom of my window, but it's sticking only to the bottom of the root window. Eventually I want to have a Treeview widget in the left pane and thumbnails in the right pane.
Can anyone help me to get the Paned Window to stick NSEW? Do I need to put it inside another frame?
I'm using Python 2.7 on Windows 7. (This isn't my whole program, just a sample to demonstrate the problem.)
#!/usr/bin/env python
# coding=utf-8
from Tkinter import *
from ttk import *
class MainWindow:
def null(self):
pass
def __init__(self):
self.root = Tk()
self.root.geometry("700x300")
self.root.resizable(width=TRUE, height=TRUE)
self.root.rowconfigure(0, weight=1)
self.root.columnconfigure(0, weight=1)
self.menubar = Menu(self.root)
File_menu = Menu(self.menubar, tearoff=0)
self.menubar.add_cascade(label="Pandoras Box", menu=File_menu)
File_menu.add_command(label="Black Hole", command=self.null)
self.root.config(menu=self.menubar)
self.toolbar = Frame(self.root, relief=RAISED)
self.toolbar.grid(row=0, column=0, sticky='NEW')
self.toolbar.grid_columnconfigure(0, weight=1)
self.toolbar.rowconfigure(0, weight=1)
dummy = Button(self.toolbar, text="Tool Button")
dummy.grid(row=0, column=0, sticky='EW')
Find = Label(self.toolbar, text="Search")
Search = Entry(self.toolbar)
Find.grid(row=0, column=5, sticky='E', padx=6)
Search.grid(row=0, column=6, sticky='E', padx=8)
self.info_column = Frame(self.root, relief=RAISED, width=100)
self.info_column.grid(row=0, column=5, rowspan=3, sticky='NSW')
self.info_column.grid_rowconfigure(0, weight=1)
self.info_column.grid_columnconfigure(0, weight=1)
self.rootpane = PanedWindow(self.root, orient=HORIZONTAL)
self.rootpane.grid(row=1, column=0, sticky='NS')
self.rootpane.grid_rowconfigure(0, weight=1)
self.rootpane.grid_columnconfigure(0, weight=1)
self.leftpane = Frame(self.rootpane, relief=RAISED)
self.leftpane.grid(row=0, column=0, sticky='NSEW')
self.rightpane = Frame(self.rootpane, relief=RAISED)
self.rightpane.grid(row=0, column=0, sticky='NSEW')
''' THESE BUTTONS ARE SUPPOSED TO BE INSIDE PANED WINDOW STUCK TO THE TOP!'''
but_left = Button(self.leftpane, text="SHOULD BE IN LEFT PANE UNDER TOOLBAR FRAME")
but_left.grid(row=0, column=0, sticky='NEW')
but_right = Button(self.rightpane, text="SHOULD BE IN RIGHT PANE UNDER TOOLBAR FRAME")
but_right.grid(row=0, column=0, sticky='NEW')
self.rootpane.add(self.leftpane)
self.rootpane.add(self.rightpane)
self.SbarMesg = StringVar()
self.label = Label(self.root, textvariable=self.SbarMesg, font=('arial', 8, 'normal'))
self.SbarMesg.set('Status Bar:')
self.label.grid(row=3, column=0, columnspan=6, sticky='SEW')
self.label.grid_rowconfigure(0, weight=1)
self.label.grid_columnconfigure(0, weight=1)
self.root.mainloop()
a = MainWindow()
Short answer: the space you see between the buttons and the toolbar frame is because you allow the row containing the toolbar to resize, instead of the row containing the PanedWindow... To get what you want, replace:
self.root.rowconfigure(0, weight=1)
with
self.root.rowconfigure(1, weight=1)
Other comments:
Try to avoid wildcard imports. In this case, it makes it difficult to differentiate between tk and ttk widgets
To allow resizing of widgets aligned using grid(), .rowconfigure(..., weight=x) must be called on the widget's parent not the widget itself.
background colors are very useful to debug alignment issues in tkinter.
Code:
import Tkinter as tk
import ttk
class MainWindow:
def __init__(self):
self.root = tk.Tk()
self.root.geometry("700x300")
self.root.resizable(width=tk.TRUE, height=tk.TRUE)
self.root.rowconfigure(1, weight=1)
self.root.columnconfigure(0, weight=1)
self.toolbar = tk.Frame(self.root, relief=tk.RAISED, bg="yellow")
self.toolbar.grid(row=0, column=0, sticky='NEW')
self.toolbar.columnconfigure(0, weight=1)
dummy = ttk.Button(self.toolbar, text="Tool Button")
dummy.grid(row=0, column=0, sticky='EW')
Find = tk.Label(self.toolbar, text="Search")
Search = ttk.Entry(self.toolbar)
Find.grid(row=0, column=5, sticky='E', padx=6)
Search.grid(row=0, column=6, sticky='E', padx=8)
self.info_column = tk.Frame(self.root, relief=tk.RAISED, width=100, bg="orange")
self.info_column.grid(row=0, column=5, rowspan=2, sticky='NSW')
self.rootpane = tk.PanedWindow(self.root, orient=tk.HORIZONTAL, bg="blue")
self.rootpane.grid(row=1, column=0, sticky='NSEW')
self.leftpane = tk.Frame(self.rootpane, bg="pink")
self.rootpane.add(self.leftpane)
self.rightpane = tk.Frame(self.rootpane, bg="red")
self.rootpane.add(self.rightpane)
''' THESE BUTTONS ARE SUPPOSED TO BE INSIDE PANED WINDOW STUCK TO THE TOP!'''
but_left = ttk.Button(self.leftpane, text="SHOULD BE IN LEFT PANE UNDER TOOLBAR FRAME")
but_left.grid(row=0, column=0, sticky='NEW')
but_right = ttk.Button(self.rightpane, text="SHOULD BE IN RIGHT PANE UNDER TOOLBAR FRAME")
but_right.grid(row=0, column=0, sticky='NEW')
self.label = tk.Label(self.root, text="Status:", anchor="w")
self.label.grid(row=3, column=0, columnspan=6, sticky='SEW')
self.root.mainloop()
a = MainWindow()

Categories

Resources