How to line up buttons on Tkinter - python

I'm using rows to layout my Tkinter program.
I usually use pack so my buttons would automatically place itself and not over lap, using rows, my buttons are overlapping, and I have to align them by changing their padx value. I was wondering if there was an easier way to do this.
from sys import argv
from Tkinter import *
from PIL import Image, ImageTk, ImageFilter
import random
script, infile = argv
class MyApp(object):
def __init__(self):
self.root = Tk()
self.root.wm_title("ImagePro")
# Original
original = Image.open(infile)
(w, h) = (original.size[0], original.size[1])
tkpi = ImageTk.PhotoImage(original)
label = Label(self.root, image=tkpi)
label.grid(row =0, column=0, padx=5,pady=5)
img = original.copy().convert("L")
tkpi2 = ImageTk.PhotoImage(img)
label = Label(self.root, image=tkpi2)
label.grid(row =0, column=1, padx=5,pady=5)
Label(self.root, text = "Original").grid(row=1, column=0)
Label(self.root, text = "Modified").grid(row=1, column=1)
Button(self.root, text = "Brighten").grid(row=2, column=0, sticky=W)
Button(self.root, text = "Darken").grid(row=2, column=0, sticky=W, padx=60)
Button(self.root, text = "Warm").grid(row=2, column=0, sticky=W, padx=112)
Button(self.root, text = "Cool").grid(row=2, column=0, sticky=W, padx=158)
self.root.mainloop()
MyApp()

To do this you need to start using frames. A frame acts as a container for widgets. Add all the buttons to a frame, then add that frame to the root container.
class MyApp(object):
def __init__(self):
self.root = Tk()
self.root.wm_title("ImagePro")
#Original
original = Image.open(infile)
(w, h) = (original.size[0], original.size[1])
tkpi = ImageTk.PhotoImage(original)
label = Label(self.root, image=tkpi)
label.grid(row =0, column=0, padx=5,pady=5)
img = original.copy().convert("L")
tkpi2 = ImageTk.PhotoImage(img)
label = Label(self.root, image=tkpi2)
label.grid(row =0, column=1, padx=5,pady=5)
Label(self.root, text = "Original").grid(row=1, column=0)
Label(self.root, text = "Modified").grid(row=1, column=1)
self.buttonframe = Frame(self.root)
self.buttonframe.grid(row=2, column=0, columnspan=2)
Button(self.buttonframe, text = "Brighten").grid(row=0, column=0)
Button(self.buttonframe, text = "Darken").grid(row=0, column=1)
Button(self.buttonframe, text = "Warm").grid(row=0, column=2)
Button(self.buttonframe, text = "Cool").grid(row=0, column=3)
self.root.mainloop()
Each button goes in its own column within the frame, and the frame goes at the bottom of the main container.

If you use the same row,column couple for several widgets, they will appear in the same cell of the grid. Thus something like this should do the trick.
Button(self.root, text = "Brighten").grid(row=2, column=0)
Button(self.root, text = "Darken").grid(row=2, column=1)
Button(self.root, text = "Warm").grid(row=2, column=2)
Button(self.root, text = "Cool").grid(row=2, column=3)
You will find detailed information on this documentation of grid geometry manager http://effbot.org/tkinterbook/grid.htm

Related

How to add a Scrollbar on the main window when only Label and Button are used

I know how to add a scrollbar on a tkinter window, frame, canvas.
I also know how to do it on a listbox.
Problem is, I have a window that doesn't have any of those, and only use Label and Button:
from tkinter import *
test1 = 100
test2 = 100
test3 = 100
test4 = 100
root = Tk()
root.title("Program")
root.geometry('350x250')
# first group of labels & buttons
label = Label(root, text="test1")
label.grid(row=0, column=0, columnspan=2)
label = Label(root, text=test1)
label.grid(row=1, column=0, columnspan=2)
button = Button(root, text="Up")
button.grid(row=2, column=0)
button = Button(root, text="Down")
button.grid(row=2, column=1)
#
label = Label(root, text="test2")
label.grid(row=3, column=0, columnspan=2)
label = Label(root, text=test2)
label.grid(row=4, column=0, columnspan=2)
button = Button(root, text="Up")
button.grid(row=5, column=0)
button = Button(root, text="Down")
button.grid(row=5, column=1)
#
label = Label(root, text="test3")
label.grid(row=6, column=0, columnspan=2)
label = Label(root, text=test3)
label.grid(row=7, column=0, columnspan=2)
button = Button(root, text="Up")
button.grid(row=8, column=0)
button = Button(root, text="Down")
button.grid(row=8, column=1)
#
label = Label(root, text="test4")
label.grid(row=9, column=0, columnspan=2)
label = Label(root, text=test4)
label.grid(row=10, column=0, columnspan=2)
button = Button(root, text="Up")
button.grid(row=11, column=0)
button = Button(root, text="Down")
button.grid(row=11, column=1)
root.mainloop()
The above has a small window resolution on purpose, because, while it may work in maximizing the window, once there are too many Label's text or Button, then a Scrollbar will be needed. This is intended to test that.
How can I add a scrollbar to the above code?
You need a scrollable frame. See example here: https://gist.github.com/mp035/9f2027c3ef9172264532fcd6262f3b01
And for buttons and labels, instead of using root as parent, use the scrollable frame as parent. For example:
from tkinter import *
c1 = "#999999"
c2 = "#000000"
class ScrollFrame(Frame):
"""
A simple scrollable frame class for tkinter
Source: https://gist.github.com/mp035/9f2027c3ef9172264532fcd6262f3b01
"""
def __init__(self, parent):
# create a frame (self)
super().__init__(parent, background=c1)
# place canvas on self
self.canvas = Canvas(
self, bd=0, bg=c1, relief="flat", highlightthickness=0
)
# place a frame on the canvas, this frame will hold the child widgets
self.viewPort = Frame(self.canvas, background=c1)
self.viewPort.grid_columnconfigure(0, weight=1)
# place a scrollbar on self
self.vsb = Scrollbar(self, orient="vertical", command=self.canvas.yview)
# attach scrollbar action to scroll of canvas
self.canvas.configure(yscrollcommand=self.vsb.set)
# pack scrollbar to right of self
self.vsb.pack(side="right", fill="y")
# pack canvas to left of self and expand to fil
self.canvas.pack(side="left", fill="both", expand=True)
self.canvas_frame = self.canvas.create_window(
(0, 0),
window=self.viewPort,
anchor="nw", # add view port frame to canvas
tags="self.viewPort",
)
# bind an event whenever the size of the viewPort frame changes.
self.viewPort.bind("<Configure>", self.onFrameConfigure)
self.canvas.bind("<Configure>", self.FrameWidth)
self.canvas.bind_all("<MouseWheel>", self._on_mousewheel)
def _on_mousewheel(self, event):
self.canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
def FrameWidth(self, event):
canvas_width = event.width
self.canvas.itemconfig(self.canvas_frame, width=canvas_width)
def onFrameConfigure(self, event):
"""Reset the scroll region to encompass the inner frame"""
# whenever the size of the frame changes, alter the scroll region respectively.
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
tests = [100, 99, 98, 101]
root = Tk()
root.title("Program")
root.geometry('350x250')
scroll_frame = ScrollFrame(root)
for i, testi in enumerate(tests):
# grouping labels and buttons together in a subframe
# so that the row numbers of the labels and buttons
# are always 0 to 2 within the sub-frame
f1 = Frame(scroll_frame.viewPort)
# first group of labels & buttons
label = Label(f1, text=f"test{i}")
label.grid(row=0, column=0, columnspan=2)
label = Label(f1, text=testi)
label.grid(row=1, column=0, columnspan=2)
button = Button(f1, text="Up")
button.grid(row=2, column=0)
button = Button(f1, text="Down")
button.grid(row=2, column=1)
# defining this group to have 2 columns with equal weight
f1.grid_columnconfigure(0, weight=1)
f1.grid_columnconfigure(1, weight=1)
# expand this sub-frame horizontally to it's parent, sticking to West and East of parent frame
f1.grid(sticky="we", ipadx=2)
# adding a separator
Frame(f1, height=1, background=c2).grid(
sticky="we", pady=5, padx=5, columnspan=2
)
# expand the scroll_frame in all 4 directions to fill the parent frame, sticking to West, East, North and South of parent frame
scroll_frame.grid(sticky="wens", row=0, column=0)
# set root frame only has 1 column (filled by scroll_frame)
root.grid_columnconfigure(0, weight=1)
root.mainloop()
I recently stumbled on an easier way to do that (also use less code to do so):
import tkinter as tk
root = tk.Tk()
text = tk.Text(wrap="none")
vsb = tk.Scrollbar(orient="vertical", command=text.yview)
text.configure(yscrollcommand=vsb.set)
vsb.pack(side="right", fill="y")
text.pack(fill="both", expand=True)
for i in range(30):
test1 = "test" + str(i)
test2 = "Button" + str(i)
c = tk.Label(text=test1)
k = tk.Label(text=i)
b = tk.Button(text=test2)
d = tk.Button(text=test2)
text.window_create("end", window=c)
text.insert("end", "\n")
text.window_create("end", window=k)
text.insert("end", "\n")
text.window_create("end", window=b)
text.window_create("end", window=d)
text.insert("end", "\n")
text.configure(state="disabled")
root.mainloop()
This is based on this answer. It doesn't use a canvas.
There is also another similar answer to the one I accepted on this post, here.

How to create Tkinter Tab frame with different (dynamic) heights

I am trying to create Tabs in python tkinter. I would like the Tab's height to size dynamically based on its content. Below is a sample of my code
from tkinter import *
from tkinter import ttk
root = Tk()
root.title('Frames')
root.geometry('500x500')
frame1 = LabelFrame(root)
frame1.pack(padx=5, pady = 5)
notebook1 = ttk.Notebook(frame1)
notebook1.pack(pady= 5)
nbframe1 = Frame(notebook1, bg = 'white')
nbframe2 = Frame(notebook1, bg = 'grey')
nbframe1.pack(fill ='both', expand=1)
nbframe2.pack(fill ='both', expand=1)
notebook1.add(nbframe1, text= 'A Search')
notebook1.add(nbframe2, text= 'B Search')
a_label = Label(nbframe1, text= 'A_Tag', bg = 'white')
a_label.grid(row = 0, column = 0, sticky=W, padx=5)
b_label = Label(nbframe1, text= 'B_Tag', bg = 'white')
b_label.grid(row = 1, column = 0, sticky=W, padx=5)
a_text = StringVar()
a_entry = Entry(nbframe1, textvariable = a_text, width=50)
a_entry.grid(row = 0, column = 1, sticky=W, padx=5)
b_text = StringVar()
b_entry = Entry(nbframe1, textvariable = b_text, width=25)
b_entry.grid(row = 1, column = 1, sticky=W, padx=5)
root.mainloop()
From my code, the Tabs created have same height even though one is empty. This is based on the height of the Tab with content. How can i set it so that each Tab's height is based only on the contents.
You can bind a function to the virtual event <<NotebookTabChanged>> to adapt the height of the notebook to the currently selected tab using the height option of the notebook:
def on_change_tab(event):
tab = event.widget.nametowidget(event.widget.select()) # get selected tab
event.widget.configure(height=tab.winfo_reqheight()) # resize notebook
With your example:
from tkinter import *
from tkinter import ttk
root = Tk()
root.title('Frames')
root.geometry('500x500')
def on_change_tab(event):
tab = event.widget.nametowidget(event.widget.select())
event.widget.configure(height=tab.winfo_reqheight())
frame1 = LabelFrame(root)
frame1.pack(padx=5, pady=5)
notebook1 = ttk.Notebook(frame1)
notebook1.pack(pady=5)
nbframe1 = Frame(notebook1, bg='white')
nbframe2 = Frame(notebook1, bg='grey')
notebook1.add(nbframe1, text='A Search')
notebook1.add(nbframe2, text='B Search')
a_label = Label(nbframe1, text='A_Tag', bg='white')
a_label.grid(row=0, column=0, sticky=W, padx=5)
b_label = Label(nbframe1, text='B_Tag', bg='white')
b_label.grid(row=1, column=0, sticky=W, padx=5)
a_text = StringVar()
a_entry = Entry(nbframe1, textvariable=a_text, width=50)
a_entry.grid(row=0, column=1, sticky=W, padx=5)
b_text = StringVar()
b_entry = Entry(nbframe1, textvariable=b_text, width=25)
b_entry.grid(row=1, column=1, sticky=W, padx=5)
root.update_idletasks() # force display update so that the initial tab is displayed correctly
notebook1.bind('<<NotebookTabChanged>>', on_change_tab) # binding to update the height
root.mainloop()

OOP based tkinter

I want button 1 on to the second frame
from tkinter import *
root =Tk()
class Graphic():
def __init__(self, master):
self.colour = "blue"
self.frame_input = Frame(master, height =100, width=100, bg="green").grid(row=0, column=0)
self.label_process = Label(master, width=30).grid(row=1, column=0)
self.frame_button = Frame(master,height=100,width=100, bg="red").grid(row=2, column=0)
self.button = Button(master, text="1", bg=self.colour).grid(row=0, column=0)
if '__main__' == __name__:
grafic = Graphic(root)
root.mainloop()
The first argument for each widget is the parent to attach to. You told it to attach to master, and it did. If you want it attached to the second frame, change:
self.button = Button(master, text="1", bg=self.colour).grid(row=0, column=0)
to:
self.button = Button(self.frame_button, text="1", bg=self.colour)
self.button.grid(row=0, column=0)
Note, this still doesn't work, because you tried to chain your grid calls, and grid returns None, so all your attributes (including self.frame_button) are None, not widgets. To fix, split the creation and layout steps for all your widgets:
self.frame_input = Frame(master, height =100, width=100, bg="green")
self.frame_input.grid(row=0, column=0)
self.label_process = Label(master, width=30)
self.label_process.grid(row=1, column=0)
self.frame_button = Frame(master,height=100,width=100, bg="red")
self.frame_button.grid(row=2, column=0)
self.button = Button(self.frame_button, text="1", bg=self.colour)
self.button.grid(row=0, column=0)

Buttons appear in the wrong column using tkinter's grid layout manager

I'm trying to make this really simple GUI using tkinter and I'm using grid as a layout manager.
But when I place a certain button in column 2, it appears to the extreme left side of the window.
I just want to place the buttons exactly where I want in the window but that doesn't seem to work.
I don't know what I'm doing wrong exactly but here's the code and a screenshot.
from tkinter import *
class GUI:
#Initialize the application window
def __init__(self):
w = 520
h = 350
self.window = Tk()
ws = self.window.winfo_screenwidth()
hs = self.window.winfo_screenheight()
x = (ws/2) -(w/2)
y = (hs/2) -(h/2)
self.window.title("Excel file import")
self.window.geometry('%dx%d+%d+%d' % (w, h, x, y))
self.window.configure(bg='#004A99')
self.window.resizable(False,False)
# self.logo = Image.open(LOGO)
# self.log = self.logo.resize((150,105),Image.ANTIALIAS)
# self.logo2 = ImageTk.PhotoImage(self.log)
# self.lbl1 = Label(self.window, image=self.logo2)
# self.lbl1.image = self.logo2
# self.lbl1.grid(row=4, column=0, ipadx=0, ipady=0, pady=0, padx=0)
self.homeDirectory = r'C:/Users/Shtlrs/Desktop/Clients folder/'
self.cfgFile = self.homeDirectory + r'cfg.ini'
#Add client button
self.addClientBtn = Button(self.window, text="Add new client", bg='#1b98e0', fg="white",
width=20, height=1)
self.addClientBtn.grid(row=2, column=2, ipadx=5, ipady=5, pady=5, padx=5)
self.addClientBtn.bind("<ButtonRelease-1>",self.addNewClient)
#Select client button
self.selectClientBtn = Button(self.window, text="Select existing client", bg='#1b98e0', fg="white",
width=20, height=1)
self.selectClientBtn.grid(row=3, column=2, ipadx=5, ipady=5, pady=5, padx=5)
self.selectClientBtn.bind("<ButtonRelease-1>",self.selectClient)
# Delete client button
self.deleteClientBtn = Button(self.window, text="Delete existing client", bg='red', fg="white",
width=20, height=1)
self.deleteClientBtn.grid(row=4, column=2, ipadx=5, ipady=5, pady=5, padx=5)
self.deleteClientBtn.bind("<ButtonRelease-1>",self.deleteClient)
#Cients dropdown ( appears next to "select existing clients")
# clients = ["Medtronic","Ancora","Momo"]
# self.clientsDropDown = ttk.Combobox(self.window,values=clients)
# self.clientsDropDown.grid(row=3,column=1, ipadx=5,ipady=5,pady=5,padx=5)
# self.clientsDropDown.current(0)
self.restart = Button(self.window, text="Restart", bg='#1b98e0', fg="white",
width=20, height=1)
self.restart.grid(row=5, column=2, ipadx=5, ipady=5, pady=5, padx=5)
self.restart.bind("<ButtonRelease-1>", self.restartAPP)
self.window.mainloop()
The code lacks a lot of other functions of course (For the bindings)
But when I run this I get:
Buttons appear in the wrong column using tkinter's grid layout manager
Actually,it is the right position.Due to the first column has no widget,so it seems it is in the "wrong" column.
You can create a frame,and put all of your buttons in it.And use .pack(anchor=Center) or .pack(anchor="center") to make the frame in the center.Also,you need to set the bg attribute of Frame to make sure they have the same color.
Followed by your code,a minimal example code is here:
from tkinter import *
class GUI:
#Initialize the application window
def __init__(self):
w = 520
h = 350
self.window = Tk()
ws = self.window.winfo_screenwidth()
hs = self.window.winfo_screenheight()
x = (ws/2) -(w/2)
y = (hs/2) -(h/2)
self.window.title("Excel file import")
self.window.geometry('%dx%d+%d+%d' % (w, h, x, y))
self.window.configure(bg='#004A99')
self.window.resizable(False,False)
self.buttonFrame = Frame(self.window,bg="#004A99") # create a new frame
self.buttonFrame.pack(anchor=CENTER) # make it center
# self.logo = Image.open(LOGO)
# self.log = self.logo.resize((150,105),Image.ANTIALIAS)
# self.logo2 = ImageTk.PhotoImage(self.log)
# self.lbl1 = Label(self.window, image=self.logo2)
# self.lbl1.image = self.logo2
# self.lbl1.grid(row=4, column=0, ipadx=0, ipady=0, pady=0, padx=0)
self.homeDirectory = r'C:/Users/Shtlrs/Desktop/Clients folder/'
self.cfgFile = self.homeDirectory + r'cfg.ini'
#Add client button
self.addClientBtn = Button(self.buttonFrame, text="Add new client", bg='#1b98e0', fg="white",width=20, height=1) # put your button in the frame.
self.addClientBtn.grid(row=2, column=2, ipadx=5, ipady=5, pady=5, padx=5)
self.addClientBtn.bind("<ButtonRelease-1>",self.addNewClient)
#Select client button
self.selectClientBtn = Button(self.buttonFrame, text="Select existing client", bg='#1b98e0', fg="white",width=20, height=1) # put your button in the frame.
self.selectClientBtn.grid(row=3, column=2, ipadx=5, ipady=5, pady=5, padx=5)
self.selectClientBtn.bind("<ButtonRelease-1>",self.selectClient)
# Delete client button
self.deleteClientBtn = Button(self.buttonFrame, text="Delete existing client", bg='red', fg="white",width=20, height=1) # put your button in the frame.
self.deleteClientBtn.grid(row=4, column=2, ipadx=5, ipady=5, pady=5, padx=5)
self.deleteClientBtn.bind("<ButtonRelease-1>",self.deleteClient)
#Cients dropdown ( appears next to "select existing clients")
# clients = ["Medtronic","Ancora","Momo"]
# self.clientsDropDown = ttk.Combobox(self.buttonFrame,values=clients) # put it in the frame.
# self.clientsDropDown.grid(row=3,column=1, ipadx=5,ipady=5,pady=5,padx=5)
# self.clientsDropDown.current(0)
self.restart = Button(self.buttonFrame, text="Restart", bg='#1b98e0', fg="white",
width=20, height=1)
self.restart.grid(row=5, column=2, ipadx=5, ipady=5, pady=5, padx=5)
self.restart.bind("<ButtonRelease-1>", self.restartAPP)
self.window.mainloop()
#You need to revise all the functions below.
def addNewClient(self):
pass
def selectClient(self):
pass
def deleteClient(self):
pass
def restartAPP(self):
pass
start = GUI()
Now it is:

Managing column width tkinter

I have reviewed the documentation on rowconfugre and columnconfigure, and I just do not quite understand how to get it working properly. With the following code, how can I get the 'src_entry' Entry box directly against the 'src' Checkbutton, regardless of what other widget is in column 1? Essentially, I need the size of the column to form to the width of whatever widget is in that space on the grid.
Thanks,
from tkinter import *
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent, background="white")
self.parent = parent
self.parent.title("TCPDUMP Creator")
self.centerWindow()
self.pack(fill=BOTH, expand=1)
menubar = Menu(self.parent)
self.parent.config(menu=menubar)
fileMenu = Menu(menubar)
fileMenu.add_command(label="Exit", command=self.quit)
menubar.add_cascade(label="File", menu=fileMenu)
self.columnconfigure(2, weight=5)
int_lbl = Label(self, text="Interface")
int_lbl.grid(row=1, column=0, sticky=W+E)
self.int_entry = Entry(self, width=15)
self.int_entry.grid(row=1, column=1)
self.anyInt = BooleanVar()
Checkbutton(self, text="Any", variable = self.anyInt).grid(row=1, column=2)
int_lbl = Label(self, text="")
int_lbl.grid(row=2, column=0, columnspan=99, sticky=W+E)
self.notSrc = BooleanVar()
Checkbutton(self, text = "Not--", variable = self.notSrc).grid(row=3, column=0, sticky=W+E)
self.srcIP = BooleanVar()
Checkbutton(self, text="Src", variable = self.srcIP).grid(row=3, column=1)
src_entry = Entry(self, width=15)
src_entry.grid(row=3, column=2)
self.AndOr = StringVar()
self.AndOr.set(None)
Radiobutton(self, text = "And", variable = self.AndOr, value = "And").grid(row=3, column=3, pady=5, padx=2, sticky=E)
Radiobutton(self, text = "Or", variable = self.AndOr, value = "Or").grid(row=3, column=4, pady=5, padx=10, sticky=W)
self.notDst = BooleanVar()
Checkbutton(self, text = "Not--", variable = self.notDst).grid(row=3, column=5, sticky=W+E)
self.dstIP = BooleanVar()
Checkbutton(self, text="Dst", variable = self.dstIP).grid(row=3,column=6, sticky=E, padx=0)
dst_entry = Entry(self, width=15)
dst_entry.grid(row=3, column=7)
int_lbl = Label(self, text="")
int_lbl.grid(row=4, column=0, columnspan=99, sticky=W+E)
self.srcordst = StringVar()
self.srcordst.set(None)
Radiobutton(self, text = "And", variable = self.srcordst, value = "And").grid(row=4, column=1, pady=5, padx=2, sticky=E)
Radiobutton(self, text = "Or", variable = self.srcordst, value = "Or").grid(row=4, column=2, pady=5, padx=10, sticky=W)
def centerWindow(self):
w = 600
h = 300
sw = self.parent.winfo_screenwidth()
sh = self.parent.winfo_screenheight()
x = (sw - w)/2
y = (sh - h)/2.7
self.parent.geometry("%dx%d+%d+%d" % (w, h, x, y))
def main():
root = Tk()
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
The best way to do layouts is to break your UI into sections, and then layout each section independently.The reason you're having difficulty is that you're trying to force everything into a single grid, but you don't have items that naturally fit into a grid. You can make it work by using lots of invisible columns and clever use of columnspan, but there are easier ways.
In this specific case, pack and a few intermediate frames is a better solution in my opinion.
From what I see, your UI is made up of four areas:
A row that has an entry for int_entry and a checkbutton
A row that has several checkboxes and radiobuttons, along with an entry
A row with an 'And' and 'Or' radiobutton
A big blank area
The way I would do it is create four frames, one for each area:
frame1 = Frame(self, ...)
frame2 = Frame(self, ...)
frame3 = Frame(self, ...)
frame4 = Frame(self, ...)
You can then use pack to stack those frames horizontally. All of them fill their area in the horizontal direction, and the last frame takes up all of the rest of the data.
frame1.pack(side="top", fill="x")
frame2.pack(side="top", fill="x")
frame3.pack(side="top", fill="x")
frame4.pack(side="top", fill="both", expand=True)
Now, you can add widgets to each frame with little concern for how they affect the rest of the display.
For example, the "Interface" label, the entry and the "Any" checkbutton can go in frame1. pack makes for a sensible choice since you want these aligned to the left of the area (I assume...).
int_lbl = Label(frame1, text="Interface")
self.int_entry = Entry(frame1, width=15)
any_cb = Checkbutton(frame1, text="Any", ...)
int_lbl.pack(side="left")
self.int_entry.pack(side="left")
any_cb.pack(side="left")
Do the same for the other frames. Within each frame you can choose to use pack or grid, as long as you consistently use pack or grid for every widget within the frame. pack is a very natural choice when you want all of your widgets aligned in one direction in the parent widget.

Categories

Resources