python pack() and grid() methods together
Asked Answered
E

3

8

Im new to python so please forgive my Noob-ness. Im trying to create a status bar at the bottom of my app window, but it seems every time I use the pack() and grid() methods together in the same file, the main app window doesn't open. When I comment out the line that says statusbar.pack(side = BOTTOM, fill = X) my app window opens up fine but if I leave it in it doesn't, and also if I comment out any lines that use the grid method the window opens with the status bar. It seems like I can only use either pack() or grid() but not both. I know I should be able to use both methods. Any suggestions? Here's the code:

from Tkinter import *
import tkMessageBox

def Quit():
 answer = tkMessageBox.askokcancel('Quit', 'Are you sure?')
 if answer:
    app.destroy()

app = Tk()
app.geometry('700x500+400+200')
app.title('Title')

label_1 = Label(text = "Enter number")
label_1.grid(row = 0, column = 0)
text_box1 = DoubleVar() 
input1 = Entry(app, textvariable = text_box1)
input1.grid(row = 0, column = 2)

statusbar = Label(app, text = "", bd = 1, relief = SUNKEN, anchor = W)
statusbar.pack(side = BOTTOM, fill = X)

startButton = Button(app, text = "Start", command = StoreValues).grid(row = 9, column = 2,  padx = 15, pady = 15)

app.mainloop() 

Any help is appreciated! Thanks!

Employer answered 24/6, 2013 at 2:10 Comment(4)
Not saying it isn't possible but the common advice given is to choose one.Globin
im only using both because I dont know how to put the status bar on the bottom of the screen using the grid and I dont know how to fill = X with the grid function either.Employer
@Jared: your comment is misleading. For all intents and purposes it is impossible.Coyne
Possible duplicate of Cannot use geometry manager pack insideReactance
C
18

You cannot use both pack and grid on widgets that have the same master. The first one will adjust the size of the widget. The other will see the change, and resize everything to fit it's own constraints. The first will see these changes and resize everything again to fit its constraints. The other will see the changes, and so on ad infinitum. They will be stuck in an eternal struggle for supremacy.

While it is technically possible if you really, really know what you're doing, for all intents and purposes you can't mix them in the same container. You can mix them all you want in your app as a whole, but for a given container (typically, a frame), you can use only one to manage the direct contents of the container.

A very common technique is to divide your GUI into pieces. In your case you have a bottom statusbar, and a top "main" area. So, pack the statusbar along the bottom and create a frame that you pack above it for the main part of the GUI. Then, everything else has the main frame as its parent, and inside that frame you can use grid or pack or whatever you want.

Coyne answered 24/6, 2013 at 2:54 Comment(2)
Cool I think I get it now... So when you say pieces do you mean classes?Employer
@terencevaughn: pieces == classes? Not necessarily. While you certainly can use classes, I meant you should divide your interface into logical groups. Each group can be implemented as a frame which contains other widgets. Each logical group can be managed separately.Coyne
A
5

Yeah thats right. In following example, i have divided my program into 2 frames. frame1 caters towards menu/toolbar and uses pack() methods wherein frame2 is used to make login page credentials and uses grid() methods.

from tkinter import *

def donothing():
    print ('IT WORKED')
root=Tk()
root.title(string='LOGIN PAGE')

frame1=Frame(root)
frame1.pack(side=TOP,fill=X)

frame2=Frame(root)
frame2.pack(side=TOP, fill=X)

m=Menu(frame1)
root.config(menu=m)

submenu=Menu(m)
m.add_cascade(label='File',menu=submenu)
submenu.add_command(label='New File', command=donothing)
submenu.add_command(label='Open', command=donothing)
submenu.add_separator()
submenu.add_command(label='Exit', command=frame1.quit)


editmenu=Menu(m)
m.add_cascade(label='Edit', menu=editmenu)
editmenu.add_command(label='Cut',command=donothing)
editmenu.add_command(label='Copy',command=donothing)
editmenu.add_command(label='Paste',command=donothing)
editmenu.add_separator()
editmenu.add_command(label='Exit', command=frame1.quit)


# **** ToolBar *******

toolbar=Frame(frame1,bg='grey')
toolbar.pack(side=TOP,fill=X)
btn1=Button(toolbar, text='Print', command=donothing)
btn2=Button(toolbar, text='Paste', command=donothing)
btn3=Button(toolbar, text='Cut', command=donothing)
btn4=Button(toolbar, text='Copy', command=donothing)
btn1.pack(side=LEFT,padx=2)
btn2.pack(side=LEFT,padx=2)
btn3.pack(side=LEFT,padx=2)
btn4.pack(side=LEFT,padx=2)

# ***** LOGIN CREDENTIALS ******
label=Label(frame2,text='WELCOME TO MY PAGE',fg='red',bg='white')
label.grid(row=3,column=1)

label1=Label(frame2,text='Name')
label2=Label(frame2,text='Password')
label1.grid(row=4,column=0,sticky=E)
label2.grid(row=5,column=0,sticky=E)

entry1=Entry(frame2)
entry2=Entry(frame2)
entry1.grid(row=4,column=1)
entry2.grid(row=5,column=1)

chk=Checkbutton(frame2,text='KEEP ME LOGGED IN')
chk.grid(row=6,column=1)

btn=Button(frame2,text='SUBMIT')
btn.grid(row=7,column=1)




# **** StatusBar ******************

status= Label(root,text='Loading',bd=1,relief=SUNKEN,anchor=W)
status.pack(side=BOTTOM, fill=X)
Attwood answered 8/5, 2017 at 6:1 Comment(0)
M
0

For single widgets, the answer is no: you cannot use both pack() and grid() inside one widget. But you can use both for different widgets, even if they are all inside the same widget. For instance:

my_canvas=tk.Canvas(window1,width=540,height=420,bd=0)
my_canvas.create_image(270,210,image=bg,anchor="center")
my_canvas.pack(fill="both",expand=True)            
originallbl = tk.Label(my_canvas, text="Original", width=15).grid(row=1,column=1)
original = tk.Entry(my_canvas, width=15).grid(row=1,column=2)

I used pack() in order to set canvas, I used grid() in order to set labels, buttons, etc. in the same canvas

Millstream answered 6/10, 2021 at 7:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.