I came up with the following code more as a reference to help me remember how to build GUI apps with TkInter. It runs great except when a click Button1 or any other widget whose command option is set to self.hello. As you can see in the code bellow, the hello function is like a place holder. While the button click works fine while running the script through IDLE, it simply causes the application to exit if you start the program by double-clicking the actual file test.pyw. My question is, why?
#Some guy somewhere
from tkinter import *
class Application:
def hello(self):
msg = messagebox.showinfo('Message Title','Message Body')
def __init__(self, parent):
parent.resizable(0,0)
parent.minsize(800, 400)
parent.title('Top Level')
# Global Padding pady and padx
pad_x = 0
pad_y = 0
# CASCADE MENU
# create a parent menu.
self.parentmenu1 = Menu(parent, tearoff=0)
#self.menubar1.add_command(label='Menu1', command=self.hello)
#create a child menu for parent menu.
self.parentmenu1_child1 = Menu(parent, tearoff=0)
self.parentmenu1_child1.add_command(label='Item1', command=self.hello)
self.parentmenu1_child1.add_command(label='Item2', command=self.hello)
self.parentmenu1_child1.add_command(label='Item3', command=self.hello)
#add child menu to parent menu.
self.parentmenu1.add_cascade(label='Menu1', menu=self.parentmenu1_child1)
#self.menubar1.add_separator()
# SINGLE MENU
# create a parent menu.
self.parentmenu1.add_command(label='Menu2', command=self.hello)
# SINGLE MENU
# create a parent menu.
self.parentmenu1.add_command(label='Menu3', command=self.hello)
# display the parent menu.
parent.config(menu=self.parentmenu1)
# Create controls
#create label
self.label1 = Label(parent, text='Label1')
#create textbox
self.textbox1 = Entry(parent)
#create button
self.button1 = Button(parent, text='Button1', command=self.hello)
#string variable to hold checkbox1 values.
self.str_checkbox1 = StringVar()
#create checkbox
self.checkbox1 = Checkbutton(parent, text='Checkbox1', variable=self.str_checkbox1, onvalue='on1', offvalue='off1')
#deselect checkbox1
self.checkbox1.deselect()
#string variable to hold checkbox2 values.
self.str_checkbox2 = StringVar()
#create checkbox
self.checkbox2 = Checkbutton(parent, text='Checkbox2', variable=self.str_checkbox2, onvalue='on2', offvalue='off2')
#deselect checkbox2
self.checkbox2.deselect()
#???? ..what sets the groupbox apart from others. primary key???!!
self.str_radiobutton1 = StringVar()
#command= parameter missing.
self.radiobutton1 = Radiobutton(parent, text='Radio 1', variable=self.str_radiobutton1, value='a')
self.radiobutton2 = Radiobutton(parent, text='Radio 2', variable=self.str_radiobutton1, value='b')
self.radiobutton1.select()
#create a list of options.
optionList = ('Option1', 'Option2', 'Option3')
#string variable to hold optionlist values.
self.str_optionmenu1 = StringVar()
#associate string variable with optionlist
self.str_optionmenu1.set(optionList[0])
#create optionmenu
self.optionmenu1 = OptionMenu(parent, self.str_optionmenu1, *optionList)
#create a frame
self.frame1 = Frame(parent)
#create a text.
self.textarea1 = Text(self.frame1, width=20, height=10)
#align text left and fill frame with it.
self.textarea1.pack(side=LEFT, fill=Y)
#create a scrollbar.
self.scrollbar1 = Scrollbar(self.frame1)
#align scrollbar right and fill frame with it.
self.scrollbar1.pack(side=RIGHT, fill=Y)
#what is going to be scrolled?
self.scrollbar1.config(command=self.textarea1.yview)
#set textarea scrollbar.
self.textarea1.config(yscrollcommand=self.scrollbar1.set)
#align frame left and fill.
self.frame1.pack(side=LEFT, fill=Y)
#create a frame
self.frame2 = Frame(parent)
#create a text.
self.listbox1 = Listbox(self.frame2, width=20, height=10, activestyle='none', selectmode=SINGLE)
#create a list of items.
optionList = ('Item1', 'Item2', 'Item3', 'Item4', 'Item5', 'Item6', 'Item7', 'Item8', 'Item9', 'Item10', 'Item11')
#add items from list to listbox
for item in optionList:
self.listbox1.insert(END, item)
#align text left and fill frame with it.
self.listbox1.pack(side=LEFT, fill=Y)
#create a scrollbar.
self.scrollbar2 = Scrollbar(self.frame2)
#align scrollbar right and fill frame with it.
self.scrollbar2.pack(side=RIGHT, fill=Y)
#what is going to be scrolled?
self.scrollbar2.config(command=self.listbox1.yview)
#set textarea scrollbar.
self.listbox1.config(yscrollcommand=self.scrollbar2.set)
#align frame left and fill.
self.frame2.pack(side=LEFT, fill=Y)
# Place controls inside of grid
self.label1.grid(row=0, column=0, padx=pad_x, pady=pad_y, sticky=W)
self.textbox1.grid(row=0, column=1, padx=pad_x, pady=pad_y, sticky=W)
self.button1.grid(row=1, column=0, padx=pad_x, pady=pad_y, sticky=W)
self.checkbox1.grid(row=1, column=1, padx=pad_x, pady=pad_y, sticky=W)
self.checkbox2.grid(row=1, column=2, padx=pad_x, pady=pad_y, sticky=W)
self.optionmenu1.grid(row=2, column=0, padx=pad_x, pady=pad_y, sticky=W)
self.frame1.grid(row=2, column=1, padx=pad_x, pady=pad_y, sticky=W)
self.radiobutton1.grid(row=3, column=0, padx=pad_x, pady=pad_y, sticky=W)
self.radiobutton2.grid(row=3, column=1, padx=pad_x, pady=pad_y, sticky=W)
self.frame2.grid(row=4, column=0, padx=pad_x, pady=pad_y, sticky=W)
if __name__ == '__main__':
parent = Tk()
app = Application(parent)
parent.mainloop()
Alright. Apparently tkMessageBox has been renamed to messagebox in Python 3.x. Also this
module is not available in tkinter so even though a developer might use:
from tkinter import *
..he/she would still need to:
from tkinter import messagebox
Related
I'd like to print the current value of the checkbox variable. Instead I get the last before the click. what am I doing wrong?
import tkinter as tk
def widget(frame):
chbx_value = 0
widget_col_span = 1
# widgets checkbox
var_c = tk.IntVar(master=frame, value=chbx_value)
widget_c = tk.Checkbutton(master=frame, text='', variable=var_c)
widget_c.bind("<ButtonRelease>", lambda event: print(var_c.get()))
widget_c.grid(row=0, column=0, columnspan=widget_col_span, padx=1, pady=1, sticky="ns")
root = tk.Tk()
root.title('My Window')
widget(root)
root.mainloop()
The event <ButtonRelease> obviously occurs before your variable has changed. My advice would be to use the command kwarg in the Checkbutton constructor. Besides, it probably makes more sense to use a boolean as variable:
import tkinter as tk
def widget(frame):
widget_col_span = 1
# widgets checkbox
var_c = tk.BooleanVar(master=frame)
widget_c = tk.Checkbutton(master=frame, text='', variable=var_c, command=lambda: print(var_c.get()))
widget_c.grid(row=0, column=0, columnspan=widget_col_span, padx=1, pady=1, sticky="ns")
root = tk.Tk()
root.title('My Window')
widget(root)
root.mainloop()
I am trying to code a tkinter application that has three frames - a top frame, where the user inputs some text, a dynamically constructed middle section where some pre-analysis is conducted on the text, and a bottom frame where, once the user has selected which option they want in the middle section, the output will be produced.
The problem is that, depending upon the input, there could be around 10-20 (and in the worst case 30) lines displayed and on a small monitor the output will disappear off the screen.
What I would like is for the top (input) and bottom (output) frames to be visible no matter how the screen is re-sized, and for the middle section to scroll (if required) and still allow the user to select their choice.
I am confused as to how to get the middle section to resize when the screen is resized, show a scrollbar if required, and still allow all of the content to be accessed.
I have created a cut-down version here (for simplicity, I have removed the processing methods and have instead created some fake output in a loop that resembles what the actual middle section would look like).
Please ignore the hideous colour-scheme - I was just trying to understand which frame went where (I will remove the colours as soon as I can!)
Thank you for any suggestions...
import tkinter as tk
from tkinter import scrolledtext
class MyApp(tk.Tk):
def __init__(self, title="Sample App", *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title(title)
self.configure(background="Gray")
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
# Create the overall frame:
master_frame = tk.Frame(self, bg="Light Blue", bd=3, relief=tk.RIDGE)
master_frame.grid(sticky=tk.NSEW)
master_frame.rowconfigure([0, 2], minsize=90) # Set min size for top and bottom
master_frame.rowconfigure(1, weight=1) # Row 1 should adjust to window size
master_frame.columnconfigure(0, weight=1) # Column 0 should adjust to window size
# Create the frame to hold the input field and action button:
input_frame = tk.LabelFrame(master_frame, text="Input Section", bg="Green", bd=2, relief=tk.GROOVE)
input_frame.grid(row=0, column=0, padx = 5, pady = 5, sticky=tk.NSEW)
input_frame.columnconfigure(0, weight=1)
input_frame.rowconfigure(0, weight=1)
# Create a frame for the middle (processing) section.
middle_frame = tk.LabelFrame(master_frame, text = "Processing Section")
middle_frame.grid(row=1, column=0, padx=5, pady=5, sticky=tk.NSEW)
# Create the frame to hold the output:
output_frame = tk.LabelFrame(master_frame, text="Output Section", bg="Blue", bd=2, relief=tk.GROOVE)
output_frame.grid(row=2, column=0, columnspan=3, padx=5, pady=5, sticky=tk.NSEW)
output_frame.columnconfigure(0, weight=1)
output_frame.rowconfigure(0, weight=1)
# Add a canvas in the middle frame.
self.canvas = tk.Canvas(middle_frame, bg="Yellow")
self.canvas.grid(row=0, column=0)
# Create a vertical scrollbar linked to the canvas.
vsbar = tk.Scrollbar(middle_frame, orient=tk.VERTICAL, command=self.canvas.yview)
vsbar.grid(row=0, column=1, sticky=tk.NS)
self.canvas.configure(yscrollcommand=vsbar.set)
# Content for the input frame, (one label, one input box and one button).
tk.Label(input_frame,
text="Please type, or paste, the text to be analysed into this box:").grid(row=0, columnspan = 3, sticky=tk.NSEW)
self.input_box = scrolledtext.ScrolledText(input_frame, height=5, wrap=tk.WORD)
self.input_box.columnconfigure(0, weight=1)
self.input_box.grid(row=1, column=0, columnspan = 3, sticky=tk.NSEW)
tk.Button(input_frame,
text="Do it!",
command=self.draw_choices).grid(row=2, column=2, sticky=tk.E)
# Content for the output frame, (one text box only).
self.output_box = scrolledtext.ScrolledText(output_frame, width=40, height=5, wrap=tk.WORD)
self.output_box.grid(row=0, column=0, columnspan=3, sticky=tk.NSEW)
def draw_choices(self):
""" This method will dynamically create the content for the middle frame"""
self.option = tk.IntVar() # Variable used to hold user's choice
self.get_input_text()
for i in range(30):
tk.Radiobutton(self.canvas,
text=f"Option {i + 1}: ", variable=self.option,
value=i,
command=self.do_analysis
).grid(row=i, column=0, sticky=tk.W)
tk.Label(self.canvas,
text=f"If you pick Option {i + 1}, the output will look like this: {self.shortText}.",
anchor=tk.W
).grid(row=i, column=1, sticky=tk.W)
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def get_input_text(self):
""" Will get the text from the input box and also create a shortened version to display on one line"""
screenWidth = 78
self.input_text = self.input_box.get(0.0, tk.END)
if len(self.input_text) > screenWidth:
self.shortText = self.input_text[:screenWidth]
else:
self.shortText = self.input_text[:]
self.shortText = self.shortText.replace('\n', ' ') # strip out carriage returns just in case
def do_analysis(self):
"""This will ultimately process and display the results"""
option = self.option.get() # Get option from radio button press
output_txt = f"You picked option {option + 1} and here is the output: \n{self.input_text}"
self.output_box.delete(0.0, tk.END)
self.output_box.insert(0.0, output_txt)
if __name__ == "__main__":
app = MyApp("My Simple Text Analysis Program")
app.mainloop()
I understand that you can't mix grid and pack geometries in the same container, and that a scrollbar must be attached to a canvas, and objects to be placed on that canvas must therefore be in yet another container so, attempting to follow Bryan's example, I created a minimal version of what I want - window with three sections - top, middle and bottom. The Top and bottom sections will contain a simple text field, the middle section will contain dynamic content and must be able to scroll as required.
Imports:
ScrollbarFrame
Extends class tk.Frame to support a scrollable Frame]
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("A simple GUI")
# Top frame
self.top_frame = tk.Frame(self, bg="LIGHT GREEN")
self.top_frame.pack(fill=tk.X)
tk.Label(self.top_frame, bg=self.top_frame.cget('bg'),
text="This is a label on the top frame")\
.grid(row=0, columnspan=3, sticky=tk.NSEW)
# Middle Frame
# Import from https://stackoverflow.com/a/62446457/7414759
# and don't change anything
sbf = ScrollbarFrame(self, bg="LIGHT BLUE")
sbf.pack(fill=tk.X, expand=True)
# self.middle_frame = tk.Frame(self, bg="LIGHT BLUE")
self.middle_frame = sbf.scrolled_frame
# Force scrolling by adding multiple Label
for _ in range(25):
tk.Label(self.middle_frame, bg=self.middle_frame.cget('bg'),
text="This is a label on the dynamic (middle) section")\
.grid()
# Bottom Frame
self.bottom_frame = tk.Frame(self, bg="WHITE")
self.bottom_frame.pack(fill=tk.X)
tk.Label(self.bottom_frame, bg=self.bottom_frame.cget('bg'),
text="This is a label on the bottom section")\
.grid(row=0, columnspan=3, sticky=tk.NSEW)
if __name__ == '__main__':
App().mainloop()
Recently, I tried to make a full application window with a side panel menu with separate frames running some functions and submitting forms in the canvas frame.
But I found that every time I click on any entry in listbox it runs the function or method without clearing the existing one .
I tried destroy() and forget() didn't work for me (maybe I didn't know exactly how to use it?!, and the destroy() function prevent using the function again till I close the whole application and run it again!) this is a photo of my problem
this is my code :
import tkinter as tk
from tkinter import ttk
class MainWindow() :
def __init__(self,root):
# menu left
self.menu_upper_frame = tk.Frame(root, bg="#dfdfdf")
self.menu_title_label = tk.Label(self.menu_upper_frame, text="menu title", bg="#dfdfdf")
self.menu_title_label.pack()
self.menu_left_container = tk.Frame(root, width=150, bg="#ababab")
self.menu_left_upper = tk.Frame(self.menu_left_container, width=150, height=150, bg="red")
self.menu_left_upper.pack(side="top", fill="both", expand=True)
# create a listbox of items
self.Lb1 = tk.Listbox(self.menu_left_upper,bg ="red", borderwidth=0, highlightthickness=0 )
self.Lb1.insert(1, "Python")
self.Lb1.insert(2, "Perl")
self.Lb1.insert(3, "C")
self.Lb1.insert(4, "PHP")
self.Lb1.insert(5, "JSP")
self.Lb1.insert(6, "Ruby")
self.Lb1.bind("<<ListboxSelect>>", self.OnClick ) #return selected item
self.Lb1.pack(fill="both", expand=True, pady=50 )
# right area
self.inner_title_frame = tk.Frame(root, bg="#dfdfdf")
self.inner_title_label = tk.Label(self.inner_title_frame, text="inner title", bg="#dfdfdf")
self.inner_title_label.pack()
self.canvas_area = tk.Canvas(root, width=500, height=400, background="#ffffff")
self.canvas_area.grid(row=1, column=1)
# status bar
self.status_frame = tk.Frame(root)
self.status = tk.Label(self.status_frame, text="this is the status bar")
self.status.pack(fill="both", expand=True)
self.menu_upper_frame.grid(row=0, column=0, rowspan=2, sticky="nsew")
self.menu_left_container.grid(row=1, column=0, rowspan=2, sticky="nsew")
self.inner_title_frame.grid(row=0, column=1, sticky="ew")
self.canvas_area.grid(row=1, column=1, sticky="nsew")
self.status_frame.grid(row=2, column=0, columnspan=2, sticky="ew")
root.grid_rowconfigure(1, weight=1)
root.grid_columnconfigure(1, weight=1)
def OnClick(self,event):
widget = event.widget
selection = widget.curselection()
value = widget.get(selection)
if value == 'Python':
self.tabtop()
def tabtop(self):
self.tabControl = ttk.Notebook(self.canvas_area, width=400) # Create Tab Control
self.tab1 = ttk.Frame(self.tabControl) # Create a tab
self.tab2 = ttk.Frame(self.tabControl)
self.tab3 = ttk.Frame(self.tabControl)
self.tab4 = ttk.Frame(self.tabControl)
self.tab5 = ttk.Frame(self.tabControl)
self.tabControl.add(self.tab1, text='Login data' ) # Add the tab
self.tabControl.add(self.tab2, text='Permission')
self.tabControl.add(self.tab3, text='Roles')
self.tabControl.add(self.tab4, text='Personal data')
self.tabControl.add(self.tab5, text='Business data')
self.tabControl.pack(expand=1, fill="both") # Pack to make visible
self.l2 = tk.Label(self.tab2, text="label 2").pack()
self.l3 = tk.Label(self.tab3, text="label 3").pack()
root = tk.Tk()
root.title("Control Panel")
root.style = ttk.Style()
root.style.theme_use("clam")
user = MainWindow(root)
root.mainloop()
If what you're really asking is how to replace an existing notebook with a new notebook, all you need to do is call destroy() on the old notebook before creating the new one.
First, define self.tabControl to None somewhere in MainWindow.__init__. Then, in tabtop you can delete the old notebook before creating the new one:
def tabtop(self):
if self.tabControl is not None:
self.tabControl.destroy()
...
I am creating a tkinter application where trying to get value from multiple checkboxes from different frames.When i am clicking the checkbox in one frame it is also checked in the other frame. I want to know how to access the checkbox value from different frames.
when trying to checking the checkbox (Tb1 in frame1) it is also checking in (NLTb1 in NLframe). I would like know how to access these two check box values separately.
from tkinter import *
def create_widgets_in_first_frame():
task_type=Button(main_frame,text='Task Type',command=call_second_frame_on_top).grid(row=6,column=0,sticky=W)
Network_Location=Button(main_frame,text='Network Location',command=call_third_frame_on_top).grid(row=7,column=0,sticky=W)
def create_widgets_in_second_frame():
T1=Label(frame1,text="Verify and ensure there is no duplicate entries present in task type",bg='Light blue')
T1.grid(row=3,columnspan=2,sticky=W)
#creating checkbutton
Tb1=Checkbutton(frame1,text='Pass',font=('Times New Roman',14),bg='Green')
Tb1.grid(row=3,column=4,padx=6)
#creating checkbuttonx
r2=Checkbutton(frame1,text='Fail',font=('Times New Roman',14),bg='red')
r2.grid(row=3,column=5,padx=6)
#creating Run button
b1=Button(frame1,text='Run').grid(row=3,column=6,padx=6)
button=Button(frame1,text='Go to Main page',command=call_first_frame_on_top)
button.grid(row=20,column=0,padx=6,sticky=W)
def create_widgets_in_third_frame():
NL1=Label(NLframe,text="Verify the migrated Network location in NGMSS and ensure all the mandatory information's are migrated along with it",bg='Light blue')
NL1.grid(row=3,columnspan=2,sticky=W)
#creating checkbutton
NLTb1=Checkbutton(NLframe,text='Pass',font=('Times New Roman',14),bg='Green')
NLTb1.grid(row=3,column=4,padx=6)
#creating checkbuttonx
nbr2=Checkbutton(NLframe,text='Fail',font=('Times New Roman',14),bg='red')
nbr2.grid(row=3,column=5,padx=6)
#creating Run button
nlb1=Button(NLframe,text='Run').grid(row=3,column=8)
button=Button(NLframe,text='Go to Main page',command= call_first_frame_on_top)
button.grid(row=20,column=0,padx=6,sticky=W)
def call_first_frame_on_top():
frame1.grid_forget()
NLframe.grid_forget()
main_frame.grid(row=0,column=0,sticky=W+E+N+S)
def call_second_frame_on_top():
NLframe.grid_forget()
main_frame.grid_forget()
frame1.grid(row=0,column=0,sticky=W+N+E+S)
def call_third_frame_on_top():
NLframe.grid(row=0,column=0,sticky=W+N+E+S)
frame1.grid_forget()
main_frame.grid_forget()
def quit_program():
root_window.destroy()
def raise_frame():
main_frame.tkraise()
root= Tk()
main_frame=Frame(root,height=30,width=500,borderwidth=10,bg='Powder Blue',highlightthickness=10,highlightcolor="red")
main_frame.grid(row=0,column=0,sticky=W+E+N+S)
frame1=Frame(root,height=30,width=500,borderwidth=10,bg='Powder Blue',highlightthickness=10,highlightcolor="red")
frame1.grid(row=0,column=0,sticky=W+N+E+S)
NLframe=Frame(root,height=30,width=500,borderwidth=10,bg='Powder Blue',highlightthickness=5,highlightcolor="red")
NLframe.grid(row=1,column=0,sticky=W+N+E+S)
create_widgets_in_third_frame()
create_widgets_in_second_frame()
create_widgets_in_first_frame()
frame1.grid_forget()
NLframe.grid_forget()
raise_frame()
root.mainloop()
`
Firstly, in your quit_program function, you call for root_window to be destroyed. You never defined this prior. My guess is you mean root.destroy()?
Secondly, I would say you might want to consider using radio buttons instead of checkboxes. Radio buttons will exclusively allow one option to be checked. This would prevent you from checking both the Pass and the Fail box on the same page.
As far as question is concerned, the reason your checkboxes are staying checked in the other frame because you are only forgetting the grid and not destroying the widgets. The grid is just what is organizing the widgets, not the actual widgets themselves. Therefore when you forget the grid and move to a new frame, the widget in that grid spot retains its state. Thats not to say destroying the widgets is the solution however. To fix your problem just make sure that you are storing the state of the button in a variable. I've tweaked your code a little bit and got it working.
from tkinter import *
def create_widgets_in_first_frame():
task_type = Button(main_frame, text='Task Type', command=call_second_frame_on_top).grid(row=6, column=0, sticky=W)
Network_Location = Button(main_frame, text='Network Location', command=call_third_frame_on_top).grid(row=7,
column=0,
sticky=W)
def create_widgets_in_second_frame():
t_var1 = BooleanVar()
t_var2 = BooleanVar()
T1 = Label(frame1, text="Verify and ensure there is no duplicate entries present in task type", bg='Light blue')
T1.grid(row=3, columnspan=2, sticky=W)
# creating checkbutton
Tb1 = Checkbutton(frame1, text='Pass', font=('Times New Roman', 14), bg='Green', variable=t_var1)
Tb1.grid(row=3, column=4, padx=6)
# creating checkbuttonx
r2 = Checkbutton(frame1, text='Fail', font=('Times New Roman', 14), bg='red', variable=t_var2)
r2.grid(row=3, column=5, padx=6)
# creating Run button
b1 = Button(frame1, text='Run').grid(row=3, column=6, padx=6)
button = Button(frame1, text='Go to Main page', command=call_first_frame_on_top)
button.grid(row=20, column=0, padx=6, sticky=W)
def create_widgets_in_third_frame():
nl_var1 = BooleanVar()
nl_var2 = BooleanVar()
NL1 = Label(NLframe,
text="Verify the migrated Network location in NGMSS and ensure all the mandatory information's are migrated along with it",
bg='Light blue')
NL1.grid(row=3, columnspan=2, sticky=W)
# creating checkbutton
NLTb1 = Checkbutton(NLframe, text='Pass', font=('Times New Roman', 14), bg='Green', variable=nl_var1)
NLTb1.grid(row=3, column=4, padx=6)
# creating checkbuttonx
nbr2 = Checkbutton(NLframe, text='Fail', font=('Times New Roman', 14), bg='red', variable=nl_var2)
nbr2.grid(row=3, column=5, padx=6)
# creating Run button
nlb1 = Button(NLframe, text='Run').grid(row=3, column=8)
button = Button(NLframe, text='Go to Main page', command=call_first_frame_on_top)
button.grid(row=20, column=0, padx=6, sticky=W)
def call_first_frame_on_top():
frame1.grid_forget()
NLframe.grid_forget()
main_frame.grid(row=0, column=0, sticky=W + E + N + S)
def call_second_frame_on_top():
NLframe.grid_forget()
main_frame.grid_forget()
frame1.grid(row=0, column=0, sticky=W + N + E + S)
def call_third_frame_on_top():
frame1.grid_forget()
main_frame.grid_forget()
NLframe.grid(row=0, column=0, sticky=W + N + E + S)
def quit_program():
root.destroy()
def raise_frame():
main_frame.tkraise()
root = Tk()
main_frame = Frame(root, height=30, width=500, borderwidth=10, bg='Powder Blue', highlightthickness=10,
highlightcolor="red")
main_frame.grid(row=0, column=0, sticky=W + E + N + S)
frame1 = Frame(root, height=30, width=500, borderwidth=10, bg='Powder Blue', highlightthickness=10,
highlightcolor="red")
frame1.grid(row=0, column=0, sticky=W + N + E + S)
NLframe = Frame(root, height=30, width=500, borderwidth=10, bg='Powder Blue', highlightthickness=5,
highlightcolor="red")
NLframe.grid(row=1, column=0, sticky=W + N + E + S)
create_widgets_in_third_frame()
create_widgets_in_second_frame()
create_widgets_in_first_frame()
frame1.grid_forget()
NLframe.grid_forget()
raise_frame()
root.mainloop()
Side note: In the future please take steps to make sure your code is readable and that you use proper naming conventions. You can find the PEP 8 Style Guide here.
I'm aiming to make a login program but the only part that confuses me is how to make the frames.I need 3 different frames but I neither know how to make a frame other the then like this:
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
and I can only make labels and widgets using that single mainframe. As far as making another one, it is beyond me. I need to know exactly place widets inside of each frame and even after creating frames I don't know how to place stuff on the grid. Would I go for the overall grid, or does something change after making the grid. I'm using the following layout for making the frame. Basically i'm hoping for a crash course in frames. Any information i've gathered doesn't make sense to me, even after I tried to put it into code.
I've got the coding part down just not the frame part.
#Import tkinter to make gui
from tkinter import *
from tkinter import ttk
import codecs
def login(*args
):
file = open("rot13.txt", "r")
lines = file.readlines()
uname = user.get()
pword = pw.get()
for i in lines:
x = i.split()
if codecs.encode(uname,'rot13') == x[0] and codecs.encode(pword,'rot13') == x[1]:
result.set("Successful")
break;
else:
result.set("Access Denied")
root = Tk()
root.title("Login")
#Configures column and row settings and sets padding
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
user = StringVar()
pw = StringVar()
result = StringVar()
user_entry = ttk.Entry(mainframe, width=20, textvariable=user)
user_entry.grid(column=2, row=1, sticky=(W, E))
pw_entry = ttk.Entry(mainframe, width=20, textvariable=pw)
pw_entry.grid(column=2, row=2, sticky=(W, E))
ttk.Label(mainframe, text="Username ").grid(column=1, row=1, sticky=W)
ttk.Label(mainframe, text="Password ").grid(column=1, row=2, sticky=W)
ttk.Label(mainframe, text="").grid(column=1, row=3, sticky=W)
ttk.Label(mainframe, text="Result").grid(column=1, row=4, sticky=W)
ttk.Label(mainframe, text="").grid(column=1, row=5, sticky=W)
ttk.Button(mainframe, text="Login", command=login).grid(column=3, row=6, sticky=W)
#Makes a spot to put in result
ttk.Label(mainframe, textvariable=result).grid(column=2, row=4, sticky=(W, E))
#Opens up with item selected and allows you to enter username without having to click it
user_entry.focus()
#Runs calculate if click enter
root.bind('<Return>', login)
root.mainloop()
I believe the key point that you are missing is that subframes of mainframe use mainframe as the parent and that widgets within subframes use the subframe as parent. Furthermore, you can then place the subframe within the mainframe and the subframe widgets within the subframe. You do not have to pass parents to .grid because each widget knows its parent. A simplified example:
from tkinter import *
root = Tk()
mainframe = Frame(root)
login = Frame(mainframe)
label = Label(login, text='label')
entry = Entry(login)
display = Frame(mainframe)
result = Label(display, text='display result')
mainframe.grid() # within root
login.grid(row=0, column=0) # within mainframe
label.grid(row=0, column=0) # within login
entry.grid(row=0, column=1) # within login
display.grid() # within mainfram
result.grid(row=2, column=0) # within display