Reputation: 2167
I'm having some trouble getting everything to line up properly using a grid with Tkinter and Python. I want to have the menu bar at the very top, and then two listboxes (one on each side), with a couple buttons between them in the middle of the window.
Currently, both listboxes are appearing on the bottom right side of the window, and the buttons are in the upper left corner, overlapping the menu buttons.
How do I deal with the grid layout of a listbox considering their size. Can they occupy more than one grid cell? For example, if I place a listbox in (row=1, column = 1) and another in row (row = 1, column = 2), would Tkinter automatically widen the cell so that it's the width of the listbox, or would it just overlap the listboxes?
def __init__(self,root):
self.frame = Frame(root, width=500)
self.frame.pack()
self.BuildMainWindow(self.frame)
self.ListboxSet = 0
self.frame.grid()
return
#displays the menu bar and options
def BuildMainWindow(self, frame):
menubar = Frame(frame,relief=RAISED,borderwidth=1)
menubar.pack()
mb_file = Menubutton(menubar,text='file')
mb_file.menu = Menu(mb_file)
mb_file.menu.add_command(label='open', command = self.openfile)
mb_file.grid(row = 1, column = 1)
mb_edit = Menubutton(menubar,text='edit')
mb_edit.menu = Menu(mb_edit)
mb_edit.grid(row=1, column = 3)
mb_file['menu'] = mb_file.menu
mb_edit['menu'] = mb_edit.menu
#upon selecting a directory from the menu and listboxes/buttons are created
def BuildListbox(self, directory):
self.listbox1 = Tkinter.Listbox()
self.listbox2 = Tkinter.Listbox()
self.listbox1.grid(row=2, column=1)
self.listbox2.grid(row=2 ,column=10)
self.listbox2.bind('<<ListboxSelect>>', lambda e:SortActions.GetWindowIndex(self,e))
self.listbox2.bind('<B1-Motion>', lambda e:SortActions.MoveWindowItem(self,e))
i = 0
for filename in sorted(os.listdir(directory)):
self.listbox1.insert(i, filename)
i = i + 1
self.bAddToListTwo = Button(self.frame, text = "->", command = lambda:SortActions.AddToListTwo(self,self.listbox1.curselection()))
self.bAddToListTwo.grid(row=5, column = 5)
self.bAddAll = Button(self.frame, text = "Add All To Playlist", command = lambda:SortActions.AddAllFiles(self))
self.bAddAll.grid(row=6, column = 5)
self.bRemoveFromListTwo = Button(self.frame, text = "Remove From Playlist", command = lambda:SortActions.RemoveFromListTwo(self,self.listbox2.curselection()))
self.bRemoveFromListTwo.grid(row=7, column = 5)
self.bSavePlaylist = Button(self.frame, text = "Save Playlist", command = lambda:SortActions.SaveList(self))
self.bSavePlaylist.grid(row=8, column = 5)
update - I got it to work. As I suspected, I had some weird frame configuration during the initialization.
def __init__(self,root):
self.BuildMainWindow(root)
self.ListboxSet = 0
return
#displays the menu bar and options
def BuildMainWindow(self, root):
menubar = Menu(root)
root.config(menu=menubar)
# Create a menu button labeled "File" that brings up a menu
filemenu = Menu(menubar)
menubar.add_cascade(label='File', menu=filemenu)
# Create entries in the "File" menu
# simulated command functions that we want to invoke from our menus
filemenu.add_command(label='Open', command=self.openfile)
filemenu.add_separator( )
filemenu.add_command(label='Quit', command=sys.exit)
#upon selecting a directory from the menu and listboxes/buttons are created
def BuildListbox(self, directory):
self.listbox1 = Tkinter.Listbox()
self.listbox2 = Tkinter.Listbox()
self.listbox1.grid(row=1, column=1, rowspan = 4, columnspan = 5)
self.listbox2.grid(row=1 ,column=15, rowspan = 4, columnspan = 5)
self.listbox2.bind('<<ListboxSelect>>', lambda e:SortActions.GetWindowIndex(self,e))
self.listbox2.bind('<B1-Motion>', lambda e:SortActions.MoveWindowItem(self,e))
i = 0
for filename in sorted(os.listdir(directory)):
self.listbox1.insert(i, filename)
i = i + 1
self.bAddToListTwo = Button(text = "->", command = lambda:SortActions.AddToListTwo(self,self.listbox1.curselection()))
self.bAddToListTwo.grid(row=1, column = 6)
self.bAddAll = Button(text = "Add All To Playlist", command = lambda:SortActions.AddAllFiles(self))
self.bAddAll.grid(row=2, column = 6)
self.bRemoveFromListTwo = Button(text = "Remove From Playlist", command = lambda:SortActions.RemoveFromListTwo(self,self.listbox2.curselection()))
self.bRemoveFromListTwo.grid(row=3, column = 6)
self.bSavePlaylist = Button(text = "Save Playlist", command = lambda:SortActions.SaveList(self))
self.bSavePlaylist.grid(row=4, column = 6)
Upvotes: 1
Views: 11483
Reputation: 309841
Tkinter widgets can occupy more than 1 grid-cell, but you need to manage the layout yourself using the columnspan
and rowspan
keywords to .grid
.
For example, to get the layout:
--------------------------------------------
| Button1 | Button2 | |
-------------------------------- Button3 |
| Label1 | Label2 | Label3 | |
--------------------------------------------
You'd need to do something like:
Button1.grid(row=0,column=0,columnspan=2)
Button2.grid(row=0,column=2)
Button3.grid(row=0,column=4,rowspan=2)
Label1.grid(row=1,column=0)
Label2.grid(row=1,column=1)
Label3.grid(row=1,column=2)
very minimal script
import Tkinter as tk
root = tk.Tk()
Button1 = tk.Button(root,text="Button1")
Button2 = tk.Button(root,text="Button2")
Button3 = tk.Button(root,text="Button3")
Label1 = tk.Label(root,text="Label1")
Label2 = tk.Label(root,text="Label2")
Label3 = tk.Label(root,text="Label3")
Button1.grid(row=0,column=0,columnspan=2)
Button2.grid(row=0,column=2)
Button3.grid(row=0,column=4,rowspan=2)
Label1.grid(row=1,column=0)
Label2.grid(row=1,column=1)
Label3.grid(row=1,column=2)
root.mainloop()
Upvotes: 6