Both frames show when using pack(). The login frame is supposed to show first, and when register is clicked, the register email frame is supposed to show.
Works fine when using grid(), but the frame doesn't fill the container. I tried doing sticky on all four corners, but it only sticks to one corner.
The size of the container might not be the problem since I made sure it expanded to fill the 400x400 window, so it's just the frames themselves causing the issue
How do I fix this?
`
import tkinter as tk
import customtkinter as ctk
class Window(ctk.CTk):
def __init__(self, *args, **kwargs):
super().__init__()
self.geometry('400x400')
self.title('Music Mayhem')
self.resizable(False, False)
container = ctk.CTkFrame(master=self)
container.pack(side='top', fill='both', expand=True)
self.frames={}
for F in (LoginFrame, RegEmailFrame):
frame = F(container, self)
self.frames[F] = frame
#frame.grid(row=0, column=0, sticky= 'n'+'e'+'s'+'w')
frame.pack(expand= True, fill = 'both')
self.show_frame(LoginFrame)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
#Create a frame to place the logo in
class LogoFrame(ctk.CTkFrame):
def __init__(self, *args, header_name="Logo Frame", **kwargs):
super().__init__(*args, **kwargs)
self.logo = ctk.CTkLabel(master=self, text='PLACE LOGO HERE')
self.logo.grid(row=0, column=0)
#First Frame that will show when app is opened
class LoginFrame (tk.Frame):
def __init__(self,parent, controller, header_name="Login"):
tk.Frame.__init__(self, parent, bg='#363635')
self.logo = LogoFrame(self, header_name='Logo')
self.logo.grid(row=0, column=0)
self.emailEntry = ctk.CTkEntry(master=self,
placeholder_text = 'Email Address',
width=150,
height=35)
self.emailEntry.grid(row=1,column=0, pady = 5)
self.passwordEntry = ctk.CTkEntry(master=self,
placeholder_text = 'Password',
width = 150,
height =35)
self.passwordEntry.grid(row=2, column = 0, pady = 5)
self.loginBtn = ctk.CTkButton(master = self,
width = 60,
height = 30,
text = 'Login')
self.loginBtn.grid(row=3, column=0, pady=10)
self.regBtn = ctk.CTkButton(master=self,
width=60,
height=20,
text = 'Register',
fg_color = 'transparent',
command= lambda:
controller.show_frame(RegEmailFrame))
self.regBtn.grid(row=4, column=0, pady=5)
class RegEmailFrame(tk.Frame):
def __init__(self, parent, controller,header_name="Register Email"):
tk.Frame.__init__(self, parent, bg='#81817e')
self.logo = LogoFrame(self)
self.logo.grid(row=0, column=0)
self.emailLabel = ctk.CTkLabel(master=self,
text='Register Email:')
self.emailLabel.grid(row=1, column=0, pady=5)
self.emailEntry = ctk.CTkEntry(master=self,
placeholder_text = 'Email Address',
width=150,
height=35)
self.emailEntry.grid(row=2, column=0)
self.contBtn = ctk.CTkButton(master=self,
width=60,
height=30,
text = 'Continue')
self.contBtn.grid(row=3, column=0, pady=5)
self.backBtn = ctk.CTkButton(master=self,
width=60,
height=20,
text = 'Back',
fg_color = 'transparent',
command= lambda:
controller.show_frame(LoginFrame))
self.backBtn.grid(row=4, column=0, pady=5)
if __name__ == '__main__':
app = Window()
app.mainloop()
`
EDIT
I tried to implement forget(). Changes to parts of the code showed below:
def show_frame(self, cont, prev):
prev = self.frames[prev]
prev.forget()
frame = self.frames[cont]
frame.tkraise()
self.regBtn = ctk.CTkButton(master=self,
width=60,
height=20,
text = 'Register',
fg_color = 'transparent',
command= lambda:
controller.show_frame(RegEmailFrame, LoginFrame))
self.backBtn = ctk.CTkButton(master=self,
width=60,
height=20,
text = 'Back',
fg_color = 'transparent',
command= lambda:
controller.show_frame(LoginFrame, RegEmailFrame))
However, an error appears :
TypeError: Window.show_frame() missing 1 required positional argument: 'prev'
SOLUTION:
for F in (LoginFrame, RegEmailFrame):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky= 'n'+'e'+'s'+'w')
frame.grid_columnconfigure(0,weight=1)
frame.grid_rowconfigure(0,weight=1)
Related
import tkinter as tk
class program(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args,**kwargs)
self.title("Staff Management System")
self.geometry("1280x720")
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
self.frames = {}
#frame that will hold all the elements
container = tk.Frame(self)
container.grid(row=0,column=0, sticky="nsew")
container.columnconfigure(0,weight=1)
container.rowconfigure(0,weight=1)
container.configure(background="blue")
#listing frames (pages) to be controlled
for F in (homePage, staffLogin):
frame = F(parent=container, controller=self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(homePage)
def show_frame(self, page):
frame = self.frames[page]
frame.tkraise()
class homePage(tk.Frame):
def __init__(self, parent, controller, *args, **kwargs):
tk.Frame.__init__(self,parent,*args, **kwargs)
for i in range(5):
self.columnconfigure(i, weight=1)
for i in range(5):
self.rowconfigure(i, weight=1)
promotionsButton = tk.Button(self, text="Promotions", height = 4)
promotionsButton.grid(row=5, column =0, sticky='w')
staffLoginButton = tk.Button(self, text="Staff Login", width = 50, height = 20, command= lambda: controller.show_frame(staffLogin))
staffLoginButton.grid(row=2, column=1)
managerLoginButton = tk.Button(self, text="Manager Login", width = 50, height = 20)
managerLoginButton.grid(row=2,column=2)
class staffLogin(tk.Frame):
def __init__(self, parent, controller, *args, **kwargs):
tk.Frame.__init__(self,parent, *args, **kwargs)
self.controller = controller
for i in range(128):
self.columnconfigure(i,weight=1)
for i in range(128):
self.rowconfigure(i,weight=1)
self.staffLabel = tk.Label(self, text = "Staff Login", font=("Helvectia", 24))
self.staffLabel.grid(row = 40, column=60)
self.userIDLabel = tk.Label(self, text = "UserID:")
self.userIDLabel.grid(sticky="W", row=67,column=59)
self.userIDInput = tk.Entry(self, width=50, font=("Helvectia",16))
self.userIDInput.grid(row=67, column=60)
self.userPasswordLabel = tk.Label(self, text = "Password:")
self.userPasswordLabel.grid(sticky="W", row=70, column=59)
self.userPasswordInput = tk.Entry(self,width=50, font=("Helvectia",16))
self.userPasswordInput.grid(row=70, column=60)
self.showPassword = tk.Button(self, text="Show Password", command=self.togglePassword())
self.showPassword.grid(sticky="W", row=71, column=60)
self.loginButton = tk.Button(self, text="Login", height=2, width=7)
self.loginButton.grid(sticky="E",row = 71, column=60)
self.backButton = tk.Button(self, text="Back To Main Menu", height=4, command= lambda: controller.show_frame(homePage))
self.backButton.grid(row=128, column=0)
def togglePassword(self):
if self.userPasswordLabel.cget("show") == "*":
self.userPasswordLabel.config(show= "")
self.showPassword.config(text="Hide Password")
else:
self.userPasswordLabel.config(show="")
self.showPassword.config(text="Show Password")
thing = program()
thing.mainloop()
im trying to create a function that runs when clicked inside of my "staff login" page. However, due to me using a new method of programming tkinter to be able to switch pages, I am unsure of how to get functions for buttons to work. currently, i get an error saying that the methods that i am trying to call do not exist. im not sure of what to do in order to be able to run functions inside of pages
For my current project with tkinter I was in the need of having multiple pages in my GUI and was able to achieve this through the answer I have linked to here Switch between two frames in tkinter.
However, I can't find a way to implement a call to a root window without ruining this preexisting code. I am trying to create a widget button to destroy the root window but I can't locate the specific root to destroy.
from tkinter import *
class MainApp(Tk):
"""Class that displays respective frame"""
def __init__(self):
Tk.__init__(self)
self.winfo_toplevel().title("YouTube Ripper and Editor")
self.resizable(0, 0)
container = Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, Downloader, Audio_Player, Config, About):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="NSEW")
self.show_frame("StartPage")
def show_frame(self, page_name):
"""Raise called frame"""
frame = self.frames[page_name]
frame.tkraise()
class StartPage(Frame):
"""Class that contains the start page"""
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.configure(bg = f_color)
self.controller = controller
b_font = Font(family = "Franklin Gothic Book", size = 12)
titleLabel = Label(self, text="Youtube Ripper and Editor", font = ("Franklin Gothic Book", 16, "bold"), bg = f_color)
titleLabel.pack(side="top", fill="x", pady= 30)
button1 = Button(self, text="Downloader", command=lambda: controller.show_frame("Downloader"),
font = b_font, bg = b_color, activebackground = bp_color)
button2 = Button(self, text="Audio Player", command=lambda: controller.show_frame("Audio_Player"),
font = b_font, bg = b_color, activebackground = bp_color)
button3 = Button(self, text="MP3 Configurator", command=lambda: controller.show_frame("Config"),
font = b_font, bg = b_color, activebackground = bp_color)
button4 = Button(self, text="About", command=lambda: controller.show_frame("About"),
font = b_font, bg = b_color, activebackground = bp_color)
button5 = Button(self, text="Exit", command=self.exit, font = b_font, bg = b_color, activebackground = bp_color)
# button1.pack(fill = 'x')
# button2.pack(fill = 'x')
# button3.pack(fill = 'x')
# button4.pack(fill = 'x')
button5.pack(fill = 'x')
def exit(self):
"""Exit program"""
MainApp.destroy()
def main():
app = MainApp()
app.mainloop()
main()
Use the reference to the root window that you have saved in StartPage's __init__, and call destroy on that
def exit(self):
"""Exit program"""
self.controller.destroy()
In my code, there are two frames. In the first one, I put in an Add button that will produce a new frame with a Combobox. The idea is to add a few Combobox like that in the first frame, pick different options for different Combobox, and then print them out in the next frame. But when I hit the Show options button in the second frame, it doesn't print out the options that I just chose in the first frame. How can I solve this?
from tkinter import *
from tkinter import ttk
list_1 = []
class Validation_Tool(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
container = Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (PageOne, PageTwo):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("PageOne")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
def quit(self):
self.destroy()
class PageOne(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
def add_compare():
global list_1
frame = Frame(self)
frame.pack()
label_1 = Label(frame, text='Options')
label_1.grid(row=0, column=0)
self.options_1 = ttk.Combobox(frame, values=['a','b','c','d','e'])
self.options_1.grid(row=1, column=0)
list_1.append(self.options_1.get())
quit_button = Button(self, text="Quit Program",
command=lambda: controller.quit())
next_button = Button(self, text="Next",
command=lambda: controller.show_frame("PageTwo"))
add_button = Button(self, text='Add', command=add_compare)
quit_button.place(relx=0.98, rely=0.98, anchor=SE)
next_button.place(relx=0.76, rely=0.98, anchor=SE)
add_button.place(relx=0.661, rely=0.98, anchor=SE)
class PageTwo(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
def button():
label = Label(self, text=list_1)
label.pack()
quit_button = Button(self, text="Quit Program",
command=lambda: controller.quit())
back_button = Button(self, text="Back",
command=lambda: controller.show_frame("PageOne"))
show_button = Button(self, text='Show options', command=button)
show_button.pack()
back_button.place(relx=0.76, rely=0.98, anchor=SE)
quit_button.place(relx=0.98, rely=0.98, anchor=SE)
if __name__ == "__main__":
root = Validation_Tool()
root.geometry('400x300+430+250')
root.title("Validation Tool")
root.mainloop()
Here's a modified version of your code that will print the options selected so far when the Next is pressed. To prevent the Comboboxes from interferring with each other a list of them and an associated StringVars is kept.
Having separate StringVars avoids the problem of choosing an option on one of them from changing it on the others — i.e. a different textvar gets associated with each one.
To make collecting all the options together into list_1, a callback function named selected() has been defined and gets "bound" to Combobox selection events. This make it so that, in addition to the above, the option selected will also get appended to the global list_1, which is what the Show options button displays.
from tkinter import *
from tkinter import ttk
list_1 = []
class Validation_Tool(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
container = Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.comboboxes = [] # Comboboxes created. ADDED
self.combobox_vars = [] # Vars for Comboboxes. ADDED.
self.frames = {}
for F in (PageOne, PageTwo):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("PageOne")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
def quit(self):
self.destroy()
class PageOne(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
# Combobox event handler. ADDED
def selected(event, var):
list_1.append(var.get()) # Append Combobox option selected.
def add_compare():
frame = Frame(self)
frame.pack()
label_1 = Label(frame, text='Options')
label_1.grid(row=0, column=0)
combobox_var = StringVar() # ADDED.
combobox = ttk.Combobox(frame, values=list('abcde'),
textvar=combobox_var) # For each Combobox. ADDED.
combobox.grid(row=1, column=0)
combobox.bind('<<ComboboxSelected>>', # Bind event handler. ADDED.
lambda event, var=combobox_var: selected(event, var)) # ADDED.
self.controller.comboboxes.append(combobox) # ADDED.
self.controller.combobox_vars.append(combobox_var) # ADDED.
quit_button = Button(self, text="Quit Program",
command=lambda: controller.quit())
next_button = Button(self, text="Next",
command=lambda: controller.show_frame("PageTwo"))
add_button = Button(self, text='Add',
command=add_compare)
quit_button.place(relx=0.98, rely=0.98, anchor=SE)
next_button.place(relx=0.76, rely=0.98, anchor=SE)
add_button.place(relx=0.661, rely=0.98, anchor=SE)
class PageTwo(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
def button():
label = Label(self, text=list_1)
label.pack()
quit_button = Button(self, text="Quit Program",
command=lambda: controller.quit())
back_button = Button(self, text="Back",
command=lambda: controller.show_frame("PageOne"))
show_button = Button(self, text='Show options', command=button)
show_button.pack()
back_button.place(relx=0.76, rely=0.98, anchor=SE)
quit_button.place(relx=0.98, rely=0.98, anchor=SE)
if __name__ == "__main__":
root = Validation_Tool()
root.geometry('400x300+430+250')
root.title("Validation Tool")
root.mainloop()
I'm trying to write a code that contains multiple pages and can be switched to when a button is clicked on. it worked initially but my widgets are not displaying, and there is neither a warning or an error message. Secondly, what is the difference between using tk and tk.TK?
from tkinter import *
import tkinter as tk
class moreTab(tk.Tk):
def __init__(self):
Tk.__init__(self)
self.geometry("1200x600")
container = Frame(self, bg='#c9e3c1')
container.pack(side = "top", fill = 'both', expand = True)
container.grid_rowconfigure(0, weight = 1)
container.grid_columnconfigure(0, weight = 1)
self.frames = {}
for q in (pageone, widget):
frame = q(container,self)
self.frames[q] = frame
frame.place(x= 0,y = 0)
self.raise_frame(pageone)
def raise_frame(self,cont):
frame = self.frames[cont]
frame.tkraise()
class widget(Frame):
def __init__(self, master, control):
Frame.__init__(self, master)
lab = tk.Label(self, text="main page")
lab.place(x = 10, y = 40)
but = tk.Button(self, text='visit start page', command=lambda:
control.raise_frame(pageone))
but.place(x = 10, y = 70)
class pageone(Frame):
def __init__(self, master, control):
Frame.__init__(self,master)
lab = Label(self, text = 'welcome to Game Analysis')
lab.place(x = 10, y = 10)
but = Button(self, text = "Start", command = lambda:
control.raise_frame(widget))
but.place(x = 10, y = 20)
app = moreTab()
app.mainloop()
It turns the issue was that you were using place(). Use the grid geometry manager. Using both import tkinter as tk and from tkinter import * is meaningless. Use one and be consistent. If you use the latter, you have everything available, hence you will write, say Button(...). But if you use the former, you will have to refer each widget like tk.Button(...).
import tkinter as tk
class moreTab(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.geometry("1200x600")
container = tk.Frame(self, bg='#c9e3c1')
container.pack(side = "top", fill = 'both', expand = True)
container.grid_rowconfigure(0, weight = 1)
container.grid_columnconfigure(0, weight = 1)
self.frames = {}
for q in (pageone, widget):
frame = q(container, self)
self.frames[q] = frame
frame.grid(row=0, column=0, sticky='nsew')
self.raise_frame(pageone)
def raise_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class widget(tk.Frame):
def __init__(self, master, control):
tk.Frame.__init__(self, master)
lab = tk.Label(self, text="main page")
lab.grid(row=0, column=0, padx=10, pady=10)
but = tk.Button(self, text='visit start page', command=lambda: control.raise_frame(pageone))
but.grid(row=1, column=0, padx=10, pady=10)
class pageone(tk.Frame):
def __init__(self, master, control):
tk.Frame.__init__(self, master)
lab = tk.Label(self, text = 'welcome to Game Analysis')
lab.grid(row=0, column=0, padx=10, pady=10)
but = tk.Button(self, text = "Start", command = lambda: control.raise_frame(widget))
but.grid(row=1, column=0, padx=10, pady=10)
app = moreTab()
app.mainloop()
So I've got a custom widget that inherits from frame and contains a canvas and a scrollbar, and a custom widget that also inherits from frame that I want to dynamically add to the canvas, resizing the scrollregion as necessary. Here's my code:
class MessageItem(Frame):
"""A message to be contained inside a scrollableContainer"""
def __init__(self, message, **kwds):
Frame.__init__(self, **kwds)
self.text = Label(self, text = message)
self.text.grid(column = 0, row = 0, sticky = N+S+E+W)
class scrollableContainer(Frame):
"""A scrollable container that can contain a number of messages"""
def initContents(self):
"""Initializes a scrollbar, and a canvas that will contain all the items"""
#the canvas that will contain all our items
self.canv = Canvas(self)
self.canv.grid(column = 0, row = 0, sticky = N+S+W)
#force Tkinter to draw the canvas
self.canv.update_idletasks()
#use the values from the canvas being drawn to determine the size of the scroll region
#note that currently, since the canvas contains nothing, the scroll region will be the same as
#the size of the canvas
geometry = self.canv.winfo_geometry()
xsize, ysize, xpos, ypos = parse_geometry_string(geometry)
self.canv['scrollregion'] = (0, 0, xsize, ysize)
#the scrollbar for that canvas
self.vscroll = Scrollbar(self, orient = VERTICAL, command = self.canv.yview )
self.vscroll.grid(column = 1, row = 0, sticky = N+S+E)
self.canv["yscrollcommand"] = self.vscroll.set
def __init__(self, **kwds):
Frame.__init__(self, **kwds)
#initialize the widget's contents
self.grid(sticky = N+S+E+W)
self.pack()
self.initContents()
#initialize the list of contents so we can append to it
self.contents = []
def addMessage(self, message):
#Add the message to the list of contents
self.contents.append(MessageItem(message))
#Add the message to the grid
self.contents[(len(self.contents) - 1)].grid(column = 0, row = (len(self.contents) - 1))
#set the new scrollable region for the canvas
scrollregionlist = self.canv['scrollregion'].split()
oldRegion = int(scrollregionlist[3])
newRegion = oldRegion + parse_geometry_string(self.contents[
(len(self.contents) - 1)].winfo_geometry())[3]
self.canv['scrollregion'] = (int(scrollregionlist[0]), int(scrollregionlist[1]),
int(scrollregionlist[2]), newRegion)
The problem I'm experiencing is that self.canv['scrollregion'] appears to disappear outside of init. In the addMessage method, in the line:
scrollregionlist = self.canv['scrollregion'].split()
The scrollregion property on self.canv returns an empty string, which I can verify by putting a
print self.canv['scrollregion']
immediately before that line
You sure a Text widget wouldn't suffice here?
anyway,
from Tkinter import *
class MessageItem(Frame):
"""A message to be contained inside a scrollableContainer"""
def __init__(self, master, message, **kwds):
Frame.__init__(self, master, **kwds)
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
self.text = Label(self, text=message, anchor='w', bg='gold')
self.text.grid(row=0, column=0, sticky='nsew')
class scrollableContainer(Frame):
"""A scrollable container that can contain a number of messages"""
def __init__(self, master, **kwargs):
Frame.__init__(self, master, **kwargs) #holds canvas & scrollbars
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
self.canv = Canvas(self, bd=0, highlightthickness=0)
self.hScroll = Scrollbar(self, orient='horizontal',
command=self.canv.xview)
self.hScroll.grid(row=1, column=0, sticky='we')
self.vScroll = Scrollbar(self, orient='vertical',
command=self.canv.yview)
self.vScroll.grid(row=0, column=1, sticky='ns')
self.canv.grid(row=0, column=0, sticky='nsew')
self.canv.configure(xscrollcommand=self.hScroll.set,
yscrollcommand=self.vScroll.set)
self.frm = Frame(self.canv, bd=2, bg='green') #holds messages
self.frm.grid_columnconfigure(0, weight=1)
self.canv.create_window(0, 0, window=self.frm, anchor='nw', tags='inner')
self.messages = []
for i in range(20):
m = MessageItem(self.frm, 'Something Profound', bd=2, bg='black')
m.grid(row=i, column=0, sticky='nsew', padx=2, pady=2)
self.messages.append(m)
self.update_layout()
self.canv.bind('<Configure>', self.on_configure)
def update_layout(self):
self.frm.update_idletasks()
self.canv.configure(scrollregion=self.canv.bbox('all'))
self.canv.yview('moveto','1.0')
self.size = self.frm.grid_size()
def on_configure(self, event):
w,h = event.width, event.height
natural = self.frm.winfo_reqwidth()
self.canv.itemconfigure('inner', width= w if w>natural else natural)
self.canv.configure(scrollregion=self.canv.bbox('all'))
def add_message(self, message):
m = MessageItem(self.frm, message, bd=2, bg='red')
m.grid(row=self.size[1], column=0, padx=2, pady=2, sticky='we')
self.messages.append(m)
self.update_layout()
root = Tk()
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
sc = scrollableContainer(root, bd=2, bg='black')
sc.grid(row=0, column=0, sticky='nsew')
def new_message():
test = 'Something Profane'
sc.add_message(test)
b = Button(root, text='New Message', command=new_message)
b.grid(row=1, column=0, sticky='we')
root.mainloop()