Tkinter - Unable to figure out how to update windows - python

First off, I'm new to coding. And I'm following a course on it. But in the meantime I want to test myself and figure things out for myself and "learn on the job" a bit with more hands on coding that I can use right away.
I've written below code to try and figure out to make a main window with 2 buttons. If I press a button, it should change the screen into the second/third screen. But instead if I fire up my exe.
It opens all 3 windows right away in separate windows. And once I press a button it opens another window. But what I would want is that the main window get's "updated" to show only the labels/pictures/buttons etc (which I did not include in the .py yet).
from tkinter import *
def second_window1():
second_window1 = Toplevel(main)
second_window1.title("Second window")
second_window1.geometry("414x896")
Label(second_window1, text ="This is the second window")#.pack()
def third_window1():
third_window1 = Toplevel(main)
third_window1.title("Third window")
third_window1.geometry("414x896")
Label(third_window1, text ="This is the third window")#.pack()
main = Tk()
main.title("Main Screen")
main.geometry('414x896')
main.configure(background = "azure2")
main.resizable(False, False)
Label(main, text = "Label_1", fg = "chartreuse2", bg = "ghostwhite", font = "Helvetica 16 bold").grid(row=1, column=1)
second_window = Tk()
second_window.title("Second Screen")
second_window.geometry('414x896')
second_window.configure(background = "azure2")
second_window.resizable(False, False)
Label(main, text = "Label_2", fg = "chartreuse2", bg = "ghostwhite", font = "Helvetica 16 bold").grid(row=1, column=1)
third_window = Tk()
third_window.title("Third Screen")
third_window.geometry('414x896')
third_window.configure(background = "azure2")
third_window.resizable(False, False)
Label(main, text = "Label_3", fg = "chartreuse2", bg = "ghostwhite", font = "Helvetica 16 bold").grid(row=1, column=1)
btn = Button(main, text ="Second Screen", command = second_window1).grid(row=1, column=1)
btn = Button(main, text ="Third Screen", command = third_window1).grid(row=2, column=1)
mainloop()
enter image description here

You would want to use a ttk.Notebook for that.
See e.g. at TkDocs.
An example that creates a UI using a Notebook is below.
def create_widgets(root, db):
"""Create the UI.
Arguments:
root: root window.
db: a connection to an sqlite3 database or None.
Returns:
A SimpleNamespace of widgets.
"""
# Set the font size.
default_font = nametofont("TkDefaultFont")
default_font.configure(size=12)
root.option_add("*Font", default_font)
# Common bindings
root.bind_all('q', do_q)
# SimpleNamespace to store widgets we need in the callbacks.
w = SimpleNamespace()
# Menu
menubar = tk.Menu(root)
root.config(menu=menubar)
filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label="Open", command=do_open)
filemenu.add_separator()
filemenu.add_command(label="Close", command=root.quit)
menubar.add_cascade(label="File", menu=filemenu)
# Notebook
n = ttk.Notebook(root)
w.n = n
n.pack(expand=1, fill='both')
f1 = ttk.Frame(n) # Pagina 1
f1.columnconfigure(1, weight=1)
f1.rowconfigure(1, weight=1)
w.f1 = f1
f2 = ttk.Frame(n) # Pagina 2
w.f2 = f2
f2.columnconfigure(0, weight=1)
f2.rowconfigure(0, weight=1)
f3 = ttk.Frame(n) # Pagina 3
w.f3 = f3
f3.columnconfigure(0, weight=1)
f3.rowconfigure(0, weight=1)
f4 = ttk.Frame(n)
f4.columnconfigure(0, weight=1)
f4.rowconfigure(0, weight=1)
w.f4 = f4
n.add(f2, text='Orders')
n.add(f3, text='Keywords')
n.add(f4, text="Bew. 800")
n.add(f1, text='Find')
# First row of page one
ttk.Label(f1, text='Look for:').grid(row=0, column=0, sticky='w')
ze = ttk.Entry(f1)
ze.grid(row=0, column=1, sticky='ew')
ze.bind('<Return>', do_seek)
w.ze = ze
zb = ttk.Button(
f1,
text='Execute',
command=do_seek
)
if db is None:
ze['state'] = 'disabled'
zb['state'] = 'disabled'
zb.grid(row=0, column=3, sticky='e')
w.zb = zb
# Second row of page 1
cols = ['hours']
tv = ttk.Treeview(f1, columns=cols, selectmode=None)
tv.column("#0", anchor=tk.CENTER)
tv.heading("#0", text="Datum")
tv.column("hours", anchor=tk.CENTER)
tv.heading("hours", text="Hours")
tv.grid(row=1, column=0, columnspan=4, sticky='nesw')
w.tv = tv
vsb = ttk.Scrollbar(f1, orient="vertical", command=tv.yview)
vsb.grid(row=1, column=4, sticky='ns')
tv.configure(yscrollcommand=vsb.set)
# First row of page 2
cols2 = ['order', 'hours']
tv2 = ttk.Treeview(f2, columns=cols2, selectmode=None, show='headings')
for c in cols2:
tv2.heading(c, text=c.capitalize())
tv2.column(c, anchor=tk.CENTER)
tv2.grid(row=0, column=0, sticky='nesw')
w.tv2 = tv2
vsb = ttk.Scrollbar(f2, orient="vertical", command=tv2.yview)
vsb.grid(row=0, column=1, sticky='ns')
tv2.configure(yscrollcommand=vsb.set)
# First row of page 3
cols3 = ['keyword', 'hours']
tv3 = ttk.Treeview(f3, columns=cols3, selectmode=None, show='headings')
for c in cols3:
tv3.heading(c, text=c.capitalize())
tv3.column(c, anchor=tk.CENTER)
tv3.grid(row=0, column=0, sticky='nesw')
w.tv3 = tv3
vsb = ttk.Scrollbar(f3, orient="vertical", command=tv3.yview)
vsb.grid(row=0, column=1, sticky='ns')
tv3.configure(yscrollcommand=vsb.set)
# First for of page 4
cols4 = ['order', 'hours']
tv4 = ttk.Treeview(f4, columns=cols4, selectmode=None, show='headings')
for c in cols4:
tv4.heading(c, text=c.capitalize())
tv4.column(c, anchor=tk.CENTER)
tv4.grid(row=0, column=0, sticky='nesw')
w.tv4 = tv4
vsb = ttk.Scrollbar(f4, orient="vertical", command=tv4.yview)
vsb.grid(row=0, column=1, sticky='ns')
tv4.configure(yscrollcommand=vsb.set)
return w

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()

Option menu alignment issue tkinter

I am trying to have two dropdown lists bellow two labels stating what they are. The problem is whenever i run it the second list is offset to the left. This takes place in the setupPage section and looks like so:
image of the issue
I have tried lots of combinations of sticky to no avail. Any help would be appreciated.
Code:
from tkinter import *
from tkinter import ttk
root = Tk()
def startPage(root):
content = ttk.Frame(root) #frame for plaing everything into
#frame = ttk.Frame(content, borderwidth=5, relief="sunken", width=200, height=100) #fram for plaxing images
lbl1 = ttk.Label(content, text="Is this a new or existing site?",font=("arial",12)) #setup of label for screen 1
yesvar = BooleanVar() #variables for check boxes later on
novar = BooleanVar()
yesvar.set(False)
novar.set(False)
one = ttk.Checkbutton(content, text="Yes", variable=yesvar, onvalue=True) #check buttons setup
two = ttk.Checkbutton(content, text="No", variable=novar, onvalue=True)
ok = ttk.Button(content, text="New", command = nextPage) #setup for buttons screen 1
cancel = ttk.Button(content, text="Existing")
content.grid(column=0, row=0) #intilises content
#frame.grid(column=0, row=0, columnspan=3, rowspan=2)
lbl1.grid(column=0, row=0, columnspan=3,pady=10,padx=10) #places the label asking the question with a gap either side for the window bindings
#name.grid(column=3, row=1, columnspan=2)
#one.grid(column=0, row=3)
#two.grid(column=1, row=3)
ok.grid(column=0, row=1,pady=10,padx=10) #places yes button 10 away from each edge
cancel.grid(column=1, row=1,pady=10,padx=10) #as above
def setupPage(root):
content = ttk.Frame(root) #frame for plaing everything into
#frame = ttk.Frame(content, borderwidth=5, relief="sunken", width=200, height=100) #fram for plaxing images
lbl1 = ttk.Label(content, text="Select meterial 1",font=("arial",12)) #setup of label for screen 1
lbl2 = ttk.Label(content, text = "Select meterial 2" ,font = ("arial",12))
content.grid(column=0, row=0)
lbl1.grid(column=0, row=0,columnspan=1, pady=10,padx=10)
lbl2.grid(column=1,row=0,columnspan=1,pady=10,padx=10)
clicked = StringVar()
clicked.set("lo2")
clicked2 = StringVar()
clicked2.set("lo2")
drop2 = OptionMenu(root, clicked2, "lo2", "mo3", "Lo2+mo3")
drop = OptionMenu(root, clicked, "lo2", "mo3", "Lo2+mo3")
drop.grid(column=0, row=1,pady=10,padx=10,sticky=NW)
drop2.grid(column=1, row=1,pady=10,padx=10,sticky=NW)
def nextPage():
global pagenum, root
for widget in root.winfo_children():
widget.destroy()
if pagenum == 1:
setupPage(root)
pagenum = 2
else :
startPage(root)
pagenum = 1
startPage(root)
pagenum = 1
root.mainloop()
The parent of the labels and the OptionMenus are different.
Changing the parents to root instead of content seems to work
from tkinter import *
from tkinter import ttk
root = Tk()
def startPage(root):
print("oi")
content = ttk.Frame(root) #frame for plaing everything into
#frame = ttk.Frame(content, borderwidth=5, relief="sunken", width=200, height=100) #fram for plaxing images
lbl1 = ttk.Label(content, text="Is this a new or existing site?",font=("arial",12)) #setup of label for screen 1
yesvar = BooleanVar() #variables for check boxes later on
novar = BooleanVar()
yesvar.set(False)
novar.set(False)
one = ttk.Checkbutton(content, text="Yes", variable=yesvar, onvalue=True) #check buttons setup
two = ttk.Checkbutton(content, text="No", variable=novar, onvalue=True)
ok = ttk.Button(content, text="New", command = nextPage) #setup for buttons screen 1
cancel = ttk.Button(content, text="Existing")
content.grid(column=0, row=0) #intilises content
#frame.grid(column=0, row=0, columnspan=3, rowspan=2)
lbl1.grid(column=0, row=0, columnspan=3,pady=10,padx=10) #places the label asking the question with a gap either side for the window bindings
#name.grid(column=3, row=1, columnspan=2)
#one.grid(column=0, row=3)
#two.grid(column=1, row=3)
ok.grid(column=0, row=1,pady=10,padx=10) #places yes button 10 away from each edge
cancel.grid(column=1, row=1,pady=10,padx=10) #as above
def setupPage(root):
#content = ttk.Frame(root) #frame for plaing everything into
#frame = ttk.Frame(content, borderwidth=5, relief="sunken", width=200, height=100) #fram for plaxing images
lbl1 = ttk.Label(root, text="Select meterial 1",font=("arial",12)) #setup of label for screen 1
lbl2 = ttk.Label(root, text = "Select meterial 2" ,font = ("arial",12))
#content.grid(column=0, row=0)
lbl1.grid(column=0, row=0,columnspan=1, pady=10,padx=10)
lbl2.grid(column=1,row=0,columnspan=1,pady=10,padx=10)
clicked = StringVar()
clicked.set("lo2")
clicked2 = StringVar()
clicked2.set("lo2")
drop2 = OptionMenu(root, clicked2, "lo2", "mo3", "Lo2+mo3")
drop = OptionMenu(root, clicked, "lo2", "mo3", "Lo2+mo3")
drop.grid(column=0, row=1,pady=10,padx=10,sticky=NW)
drop2.grid(column=1, row=1,pady=10,padx=10,sticky=NW)
def nextPage():
print("oi2")
global pagenum, root
for widget in root.winfo_children():
widget.destroy()
if pagenum == 1:
print("oi3")
setupPage(root)
pagenum = 2
else :
startPage(root)
pagenum = 1
startPage(root)
pagenum = 1
root.mainloop()

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:

How to make the GUI using Tkinter of the format specified below?

In the code given below, I want to create a GUI in such a way that 1) In the top frame: 1st row : "x"(checkbutton), right to "x"(checkbutton) must be "Choose xFile"(button) and right to "Choose xFile"(button) must be "clear"(button) and likewise in the 2nd row : for "y". Only when the "x" checkbutton is checked, the "choose xFile" button should gets enabled. And when clicked upon "choose xFile", it has to open the file dialogbox. And the choosen file contents should get displayed using "description box" below the "Input data"(label) in the middle frame(with both horizontal and vertical scrollbar). And when "clear" button is clicked, only the selected file contents(x or y file choosen) in the "description box" must be cleared and it must enable the "Choose xFile"(button) or "Choose yFile"(button) to perform the task again(i.e to open the file dialog box). Below to the "description box" must contain "Reset" button and to the right of "Reset" button must be "Submit" button in the middle portion of the middle frame. When the "Reset" button is clicked, all the contents being displayed in the "description box" must be cleared and the all the checkboxes must be unchecked so that the user can perform the selection process again. In the bottom frame, below "Model Output"(label), a "description box" along with "horizontal" and "vertical" scrollbar must be there. Below to the "description box" must contain "Exit" button which is placed in the middle of the "bottom frame".
from tkinter import *
def forButton1():
filename1 = askopenfilename()
with open(filename1) as f:
for i in f:
myList.insert(END, i)
print(filename1)
def forButton2():
filename1 = askopenfilename()
with open(filename1) as f:
for i in f:
myList.insert(END, i)
print(filename1)
def forButton7():
root.destroy()
root = Tk()
root.title("Spatialization of DSSAT")
topFrame = LabelFrame(root, text = "Select input file")
MyVar1 = IntVar()
MyVar2 = IntVar()
MyCheckbutton1 = Checkbutton(topFrame, text="x", variable=MyVar1)
#MyCheckbutton1.grid(row=0, column=0)
MyCheckbutton1.pack()
MyCheckbutton2 = Checkbutton(topFrame, text="y", variable=MyVar2)
#MyCheckbutton2.grid(row=1, column=0)
MyCheckbutton2.pack()
Button1 = Button(topFrame, text = "Choose xFile", command = forButton1)
#button1.grid(row=0, column=1)
Button1.pack()
Button2 = Button(topFrame, text = "Choose yFile", command = forButton2)
#button2.grid(row=0, column=1)
Button2.pack()
Button3 = Button(topFrame, text = "Clear")
Button3.pack()
Button4 = Button(topFrame, text = "Clear")
Button4.pack()
topFrame.pack(side=TOP)
middleFrame = Frame(root)
label1 = Label(middleFrame, text = "Input data:")
label1.grid(row = 4)
scrollbar = Scrollbar(middleFrame)
myList = Listbox(middleFrame, yscrollcommand = scrollbar.set)
myList.pack()
scrollbar.config( command = myList.yview )
scrollbar.pack()
Button5 = Button(middleFrame, text = "Reset")
#button1.grid(row=0, column=1)
Button5.pack()
Button6 = Button(middleFrame, text = "Submit")
#button1.grid(row=0, column=1)
Button6.pack()
middleFrame.pack()
bottomFrame = Frame(root)
label2 = Label(bottomFrame, text = "Model Output:")
label2.grid(row = 10)
Button7 = Button(bottomFrame, text = "Exit", command = forButton7)
#button1.grid(row=0, column=1)
Button7.pack()
bottomFrame.pack()
root.geometry("500x500")
root.mainloop()
Here I have fixed the placement of the given widgets (not their functionalities) as asked in question. You can follow this way to get your desired format:
from tkinter import *
from tkinter import filedialog
def forButton1():
filename1 = filedialog.askopenfilename()
with open(filename1) as f:
for i in f:
myList.insert(END, i)
print(filename1)
def forButton2():
filename1 = filedialog.askopenfilename()
with open(filename1) as f:
for i in f:
myList.insert(END, i)
print(filename1)
def forButton7():
root.destroy()
root = Tk()
root.title("Spatialization of DSSAT")
root.grid_columnconfigure(0, weight=1)
topFrame = LabelFrame(root, text="Select input file")
topFrame.grid(row=0, column=0, padx=8, pady=8, sticky=N+E+S+W)
topFrame.grid_rowconfigure(0, weight=1)
topFrame.grid_rowconfigure(1, weight=1)
topFrame.grid_columnconfigure(0, weight=1)
topFrame.grid_columnconfigure(1, weight=1)
topFrame.grid_columnconfigure(2, weight=1)
middleFrame = LabelFrame(root, text="Input data")
middleFrame.grid(row=1, column=0, padx=8, pady=8, sticky=N+E+S+W)
middleFrame.grid_rowconfigure(0, weight=1)
middleFrame.grid_rowconfigure(1, weight=0)
middleFrame.grid_columnconfigure(0, weight=1)
middleFrame.grid_columnconfigure(1, weight=1)
bottomFrame = LabelFrame(root, text="Model Output")
bottomFrame.grid(row=2, column=0, padx=8, pady=8, sticky=N+E+S+W)
bottomFrame.grid_rowconfigure(0, weight=1)
bottomFrame.grid_columnconfigure(0, weight=1)
MyVar1 = IntVar()
MyVar2 = IntVar()
MyCheckbutton1 = Checkbutton(topFrame, text="x", variable=MyVar1)
MyCheckbutton1.grid(row=0, column=0, padx=4, pady=4)
Button1 = Button(topFrame, text="Choose xFile", command=forButton1)
Button1.grid(row=0, column=1, padx=4, pady=4)
Button3 = Button(topFrame, text="Clear")
Button3.grid(row=0, column=2, padx=4, pady=4)
MyCheckbutton2 = Checkbutton(topFrame, text="y", variable=MyVar2)
MyCheckbutton2.grid(row=1, column=0, padx=4, pady=4)
Button2 = Button(topFrame, text="Choose yFile", command=forButton2)
Button2.grid(row=1, column=1, padx=4, pady=4)
Button4 = Button(topFrame, text="Clear")
Button4.grid(row=1, column=2, padx=4, pady=4)
innerMiddleFrame = Frame(middleFrame)
innerMiddleFrame.grid(row=0, column=0, columnspan=2, padx=4, pady=4)
innerMiddleFrame.grid_columnconfigure(0, weight=1)
innerMiddleFrame.grid_columnconfigure(1, weight=0)
scrollbar = Scrollbar(innerMiddleFrame)
myList = Listbox(innerMiddleFrame, yscrollcommand=scrollbar.set)
myList.grid(row=0, column=0, sticky=N+E+S+W)
scrollbar.config(command=myList.yview)
scrollbar.grid(row=0, column=1, sticky=N+E+S+W)
Button5 = Button(middleFrame, text="Reset")
Button5.grid(row=1, column=0, padx=4, pady=4)
Button6 = Button(middleFrame, text="Submit")
Button6.grid(row=1, column=1, padx=4, pady=4)
Button7 = Button(bottomFrame, text="Exit", command=forButton7)
Button7.grid(row=0, column=0, padx=4, pady=4)
root.geometry("250x425")
root.mainloop()

Categories

Resources