I'm using Tkinter in Python to create a planner. I'm trying to figure out how to pass variables from one window/class to another, using Tkinter buttons. For example, how do I introduce the string variable 'user_input' in 'StartPage' to the 'CalendarToday' window. The button that directs the user to the 'CalendarToday' page from the start page is 'btn_today'. Is there any way to make this button pass the user_input variable to the 'CalendarToday' class?
class SampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self._frame = None
self.switch_frame(StartPage)
def switch_frame(self, frame_class):
#variable = None
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy()
self._frame = new_frame
self._frame.pack()
class StartPage(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
master.title("My Calendar")
tk.Label(self, text="My Calendar!", font=('Helvetica', 16, "bold")).grid(row = 1, column = 2, pady = 35)
# Today's Calendar button
btn_today = tk.Button(self, text="Today's Calendar", width = 20, height = 3, command=lambda: master.switch_frame(Calendar_Today))
btn_today.grid(row = 3, column = 2, pady = 40, padx = 60)
# Entry Form
entry_form = tk.Entry(self)
entry_form.insert(0, 'Month, Year')
# user_input is the string variable holding the the user's input of month and year.
user_input = entry_form.get()
print(user_input)
entry_form.grid(row = 4, column = 2, pady = 0)
# Specify Calendar button
btn_specify = tk.Button(self, text="Specify month",width = 20, height = 3,command=lambda: master.switch_frame(PageTwo))
btn_specify.grid(row = 5, column = 2, pady = 10)
# Quit button
btn_quit = tk.Button(self, text="Quit App",width = 20, height = 3,command=master.destroy)
btn_quit.grid(row = 6, column = 2, pady = 20)
class Calendar_Today(tk.Frame):
def __init__(self, master):
month_display = month_today + " " + year_today
tk.Frame.__init__(self, master)
master.title(month_display)
lbl_display = tk.Label(self, text= month_display)
lbl_display.grid(row = 1, column = 2)
btn_date1 = tk.Button(self, text="Dates", width = 4, height = 2)
btn_date1.grid(row = 3, column = 2, padx = 10, pady = 10)
########################################
btn_next = tk.Button(self, text="Next Month")
btn_next.grid(row = 8, column = 1, padx = 10, pady = 10)
btn_previous = tk.Button(self, text="Previous Month")
btn_previous.grid(row = 8, column = 2, padx = 10, pady = 10)
btn_return = tk.Button(self, text="Return to Menu",command=lambda: master.switch_frame(StartPage))
btn_return.grid(row = 8, column = 3, padx = 10, pady = 10)
if __name__ == "__main__":
app = SampleApp()
app.title("My Calendar!")
app.mainloop()
You can modify switch_frame() to accept optional arguments and pass these arguments to page classes:
from tkinter import messagebox
...
class SampleApp(tk.Tk):
...
def switch_frame(self, frame_class, *args, **kw): # added optional arguments
if self._frame:
self._frame.destroy()
self._frame = frame_class(self, *args, **kw) # pass optional arguments to frame class
self._frame.pack()
class StartPage(tk.Frame):
def __init__(self, master):
...
# Today's Calendar button
btn_today = tk.Button(self, text="Today's Calendar", width=20, height=3,
command=self.show_calendar)
btn_today.grid(row=3, column=2, pady=40, padx=60)
...
def show_calendar(self):
user_input = self.entry_form.get().strip()
tokens = user_input.split()
# make sure month and year are specified
# need to do some other validations to make sure valid month and year are input
if len(tokens) == 2:
# pass the user input to Calendar_Today class
self.master.switch_frame(Calendar_Today, *tokens)
else:
messagebox.showerror("Error", f"Invalid input: {user_input}")
class Calendar_Today(tk.Frame):
def __init__(self, master, month_today, year_today): # added month and year arguments
...
Related
I'm trying to create my own Frame in tkinter but I have some problems with OOP. Below is my code.
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import *
class Listbox(tk.Listbox):
def __init__(self, master, addValues = False, values = None, *args, **kwargs):
tk.Listbox.__init__(self, master, *args, **kwargs)
# Tooltip
self.lListOver = [-1, None, None]
self.bind('<Motion>', lambda e: self.f_coord(e, l = self))
self.bind('<Leave>', self.f_resetnListOver)
if addValues:
for value in values:
self.insert(END, value)
def f_coord(self, e, l):
xEnrPos, yEnrPos = e.x, e.y
idxOver = l.nearest(yEnrPos)
lListCom = l.get(0, END)
tLast = l.bbox(len(lListCom) - 1)
if tLast is not None:
yDownLast = tLast[1] + tLast[3]
if yEnrPos > yDownLast:
if self.lListOver[1] is not None:
self.f_resetnListOver(None)
return None
if idxOver != self.lListOver[0]:
sX, sY = str(l.winfo_pointerx() + 15), str(l.winfo_pointery() + 15)
if self.lListOver[1] is not None: self.lListOver[1].destroy()
self.lListOver[1] = tk.Toplevel(l.master)
self.lListOver[1].wm_geometry("+" + sX + "+" + sY)
self.lListOver[1].wm_overrideredirect(True)
tk.Label(self.lListOver[1], text = lListCom[idxOver], bg = "#217346", bd = 1, justify = tk.LEFT).pack(padx = 2, pady = 2)
self.lListOver[0] = idxOver
return None
def f_resetnListOver(self, *d):
if self.lListOver[1] is None: return None
self.lListOver[0] = -1
self.lListOver[1].destroy()
self.lListOver[1] = None
self.lListOver[2] = None
return None
class ListboxFrame(ttk.Frame):
def __init__(self, master, labelText, *args, **kwargs):
ttk.Frame.__init__(self, master)
# Listbox
ttk.Label(self, text = labelText).grid(row = 0, column = 0, columnspan = 3)
self.listbox = Listbox(self, height = 5, *args, **kwargs)
self.listbox.grid(row = 1, column = 0, columnspan = 3, padx = 2, pady = 2)
# Entry
self.entry = ttk.Entry(self)
self.entry.grid(row = 2, column = 0, padx = 2, pady = 2)
# Buttons
self.addButton = ttk.Button(self, text = "Add", width = 4, command = self.Add)
self.addButton.grid(row = 2, column = 1, padx = 1, pady = 1)
self.deleteButton = ttk.Button(self, text = "Delete", width = 6, command = self.Delete)
self.deleteButton.grid(row = 2, column = 2, padx = 1, pady = 1)
def Add(self):
if self.entry.get() == "": return
self.listbox.insert(END, self.entry.get())
self.entry.delete(0, END)
def Delete(self):
for index in reversed(self.listbox.curselection()):
self.listbox.delete(index)
# listbox.config(height = listbox.size())
root = tk.Tk()
frame = ListboxFrame(root, "Listbox", addValues = True, values = ["Name", "Surname"], height = 10)
frame.pack()
root.mainloop()
What I'm trying to do here is to set the default height of my listbox in Frame to 5
self.listbox = Listbox(self, height = 5, *args, **kwargs)
but then when I want to create an instance of this Frame, I would like to pass another value of height
frame = ListboxFrame(root, "Listbox", addValues = True, values = ["Name", "Surname"], height = 10)
Here I'm also passing addValues and values arguments of my Listbox class. Unfortunately my code doesn't work and I got the error:
33
34 root = tk.Tk()
---> 35 frame = ListboxFrame(root, "Listbox", addValues = True, values = ["Name", "Surname"], height = 10)
36 frame.pack()
37 root.mainloop()
<ipython-input-135-115c7d7ebda4> in __init__(self, master, labelText, *args, **kwargs)
5 # Listbox
6 ttk.Label(self, text = labelText).grid(row = 0, column = 0, columnspan = 3)
----> 7 self.listbox = Listbox(self, height = 5, *args, **kwargs)
8 self.listbox.grid(row = 1, column = 0, columnspan = 3, padx = 2, pady = 2)
9
TypeError: type object got multiple values for keyword argument 'height'
I'm pretty new in OOP and Tkinter hence I hope you will be able to help me with this code to make it work.
I want to navigate to different pages of the GUI and on some pages, I need a timer if the timer expires then it will automatically redirect the user to Startpage. or if the user navigate then also timer will stop and the user will land on another page. The problem is that the timer of other pages is running in background and randomly takes user to start page. I am not able to figure out how to solve this
The code I developed is as follows:
import os
from itertools import cycle
import PIL.ImageTk, PIL.Image
import tkinter.font as font
import tkinter as tk
from tkinter import ttk
from tkinter.ttk import *
from tkinter import *
from tkinter import messagebox
import time
from time import sleep
from threading import Thread
LARGEFONT = ("Roboto", 35)
directory = r"C:\Users\mojave\tkinter\bg_images"
images = []
for filename in os.listdir(directory):
if filename.endswith(".jpg"):
images.append(os.path.join(directory,filename))
else:
continue
print(images)
#images = ["bg1.jpg", "bg2.jpg", "bg3.jpg"]
photos = cycle(PIL.ImageTk.PhotoImage(file=image) for image in images)
class tkinterApp(tk.Tk):
def __init__(self,*args,**kwargs):
tk.Tk.__init__(self,*args,**kwargs)
container = tk.Frame(self)
container.pack(side = "top", fill = "both", expand = True)
container.grid_rowconfigure(0,weight = 1)
container.grid_columnconfigure(0,weight = 1)
self.geometry('%dx%d' % (1366, 768))
self.frames = {}
for F in (StartPage, Page1, Page2):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0,column = 0, sticky = "nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
frame.event_generate("<<ShowFrame>>")
def get_page(self, page_class):
return self.frames[page_class]
# 1 second(s)
class StartPage(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
self.photo = PhotoImage(file = r"recycle_icon.png")
self.photoimage = self.photo.subsample(20,20)
btnFont = font.Font(family='Roboto',size=32,weight='bold')
#app.geometry('%dx%d' % (1366, 768))
global displayCanvas
displayCanvas = ttk.Label(self)
displayCanvas.place(x=0,y=0)
self.after(10,lambda: slideShow())
label = ttk.Label(self,text="StartPage", font=LARGEFONT)
label.grid(row=0, column=4, padx=10, pady=10)
button1 = ttk.Button(self,text="Page 1", command=lambda: controller.show_frame(Page1))
button1.grid(row=1, column=1, padx=10, pady=10)
button2 = ttk.Button(self, text = "page 2",
command = lambda : controller.show_frame(Page2))
button2.grid(row = 2, column = 1,padx = 10,pady = 10)
start_btn = tk.Button(self,text="\nStart Recycle",height=650, width=300,image=self.photoimage,
compound= TOP, command=lambda: controller.show_frame(Page1), activebackground="green", background="red", foreground="white", bd=5)
start_btn['font'] = btnFont
#start_btn.pack(side=TOP)
start_btn.place(x=1010,y=60)
self.bind("<<ShowFrame>>", self.on_show_frame)
def on_show_frame(self,event):
print("start page is shown..")
class Page1(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
#label = ttk.Label(self, text = "Page 1", font = LARGEFONT)
#label.grid(row = 0,column = 4,padx = 10,pady = 10)
lang_btnFont = font.Font(family='Roboto',size=32,weight='bold')
self.photo = PhotoImage(file = r"recycle_icon.png")
self.photoimage = self.photo.subsample(20,20)
self.img1 = PIL.ImageTk.PhotoImage(file=r'C:\\Users\\mojave\\tkinter\\bg_image.jpg')
displayCanvas1 = ttk.Label(self)
displayCanvas1.config(image=self.img1)
displayCanvas1.place(x=0,y=0)
lang_btn = tk.Button(self,text="English",height=300,
width=300,image=self.photoimage,compound=TOP, command= lambda : controller.show_frame(Page2),
activebackground= "green",background="red",foreground="white")
lang_btn['font'] = lang_btnFont
lang_btn.place(x=1010,y=60)
lang_btn2 = tk.Button(self,text="हिन्दी",height=300, width=300,image=self.photoimage,compound=TOP,
command= lambda : controller.show_frame(Page2), activebackground=
"green",background="red",foreground="white")
lang_btn2['font'] = lang_btnFont
lang_btn2.place(x=1010,y=400)
button1 = ttk.Button(self, text ="StartPage",image=self.photoimage,command= lambda :
controller.show_frame(StartPage))
button1.grid(row = 1, column = 1,padx = 10,pady = 10)
button2 = ttk.Button(self,text = "Page 2", command = lambda : controller.show_frame(Page2))
button2.grid(row = 2, column = 1,padx = 10,pady = 10)
self.timer_label1 = tk.Label(self,font = LARGEFONT, text="10s")
self.timer_label1.place(x=2,y=200)
self.timer_thread = Thread(target = self.on_show_frame)
self.timer_thread.start()
self.after(100,self.on_show_frame)
self.bind("<<ShowFrame>>", self.on_show_frame)
def on_show_frame(self,event=None):
print("page1 is shown..")
self.start = 10
self.temp = self.start
while self.temp >= 0:
self.timer_label1.config(text = str(self.temp)+ "s")
self.timer_label1.update()
if self.temp == 0:
self.timer_thread._is_running = False
show_frame_g(StartPage)
break
self.temp -=1
sleep(1)
class Page2(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self, parent)
label = ttk.Label(self,text = "Page 2", font = LARGEFONT)
label.grid(row = 0,column = 4,padx=10,pady = 10)
self.img1 = PIL.ImageTk.PhotoImage(file=r'C:\\Users\\mojave\\tkinter\\bg_image2.jpg')
displayCanvas1 = ttk.Label(self)
displayCanvas1.config(image=self.img1)
displayCanvas1.place(x=0,y=0)
button1 = ttk.Button(self, text = "Page 1",command = lambda : controller.show_frame(Page1))
button1.grid(row = 1,column = 1, padx = 10,pady = 10)
button2 = ttk.Button(self,text="Start Page", command = lambda : controller.show_frame(StartPage))
button2.grid(row = 2, column = 1,padx = 10, pady = 10)
self.bind("<<ShowFrame>>", self.on_show_frame)
def on_show_frame(self,event):
print("page2 is shown..")
#self.after(10000,lambda : show_frame_g(StartPage))
app = tkinterApp()
show_frame_g = app.show_frame
#def time_update():
# onTime_page2 =+ 1
def slideShow():
img = next(photos)
displayCanvas.config(image=img)
app.after(1000,slideShow) #after 1s
app.mainloop()
The problem is that the timer of other pages is running in background and randomly takes user to start page. I am not able to figure out how to solve this
I am using Tkinter in Python 3 to create a converter between hex, binary and denary - while creating my own methods for conversions instead of using the built in methods.
I've completed the denary to binary conversion through the use of my 'highestPowerOf2' method in the DenToBin class. I want to use this method in my HexToBin class, but whenever I try to, an additional blank window pops up and I receive - AttributeError: 'NoneType' object has no attribute 'title' - error.
How would I run 'highestPowerOf2' in the HexToBin class?
(also sorry for any poor programming practise)
Code:
from tkinter import *
from functools import partial
class Menu(Frame):
def __init__(self, master= None): # initialise Menu
Frame.__init__(self, master) # initialise Frame
self.master = master # what does this do
self.createWindow()
def createWindow(self):
self.pack(fill = BOTH, expand = 1)
denToBin = Button(self, text = 'Denary to Binary', command = lambda: self.changeWindow(DenToBin))
denToBin.pack(fill = X, padx = 10, pady = 10)
hexToBin = Button(self, text = 'Hex to Binary', command = lambda: self.changeWindow(HexToBin))
hexToBin.pack(fill = X, padx = 10, pady = 10)
def changeWindow(self, object):
root.withdraw()
currentFrame = object(root)
class DenToBin(Toplevel):
def __init__(self, master = None):
Toplevel.__init__(self, master)
self.master = master
self.Window()
self.denary = 0
def Window(self):
# print(self.denary) -- Why is this not recognised?????????
self.master.title('Unit Converter: Denary to Binary')
instructionDen = Label(self, text = 'Denary Value: ')
instructionDen.grid(row = 1, column = 0, padx = 10)
instructionBin = Label(self, text = 'Binary Value: ')
instructionBin.grid(row = 2, column = 0, padx = 10)
self.denaryEntry = Entry(self)
self.denaryEntry.grid(row = 1, column = 2, padx = 10, pady = 5)
convertButton = Button(self, text = 'Convert!', command = lambda: self.highestPowerOf2(10)) # as an example
convertButton.grid(row = 3, column = 1)
# finds highest power of 2 that is less than denary number - helps self.convert()
def highestPowerOf2(self,number):
print('I find the highest power of 2 that fits into the number given.')
class HexToBin(Toplevel):
def __init__(self, master = None):
Toplevel.__init__(self, master)
self.master = master
self.Window()
self.denary = 0
def Window(self):
self.master.title('Unit Converter: Hexadecimal to Binary')
instructionHex = Label(self, text = 'Hexadecimal Value: ')
instructionHex.grid(row = 1, column = 0, padx = 10)
instructionBin = Label(self, text = 'Binary Value: ')
instructionBin.grid(row = 2, column = 0, padx = 10)
self.hexadecimalEntry = Entry(self)
self.hexadecimalEntry.grid(row = 1, column = 2, padx = 10, pady = 5)
convertButton = Button(self, text = 'Convert!', command = self.convert)
convertButton.grid(row = 3, column = 1)
def convert(self):
# I need to call the 'highestPowerOf2' method here.
pass
root = Tk()
unitConverter = Menu(root) # root is master
root.mainloop()
I'm trying to automate some work to process data that is brought in from SQL. Towards the start of my full code I found and altered the below class from elsewhere on the site to act as a smooth interface so others can use the code too.
The aim of this is to retrieve the desired 'MPAN' and a year from the options. The combo-boxes are populated exactly as I wished, however the problem comes when trying to retrieve the selected values as global variables, and close the GUI when clicking 'Submit', as it stands nothing happens and the values are not obtained, but there is no error produced.
My assumption would be I've made a mistake with my 'getMPAN' function, though I am not very experienced with this level of tkinter so would greatly apprciate a hand. For simplicity sake I have added the category dictionary to act as mock data.
b2=[[2018],[2019],[2020],[2021],[2022],[2023],[2024],[2025]]
category = {'home': ['utilities','rent','cable'],
'car': ['gas','oil','repairs'],
'rv':['parks','maintenance','payment']}
params=''
mpan=''
year=''
class Application(Frame):
def __init__(self, master=None, Frame=None):
Frame.__init__(self, master)
super(Application,self).__init__()
self.grid(column = 5,row = 20,padx = 50,pady = 50)
self.createWidgets()
def getUpdateData(self, event):
self.AccountCombo['values'] = category[self.CategoryCombo.get()]
self.AccountCombo.current(0)
def createWidgets(self):
tk.Label(text = 'Area Code:').grid(row = 2,column = 1,padx = 10)
tk.Label(text = 'MPAN:').grid(row = 4,column = 1,padx = 10)
tk.Label(text = 'Year:').grid(row = 6, column = 1, padx = 10)
self.AccountCombo = ttk.Combobox( width = 15)
self.AccountCombo.grid(row = 5,column = 1,pady = 25,padx = 10)
self.CategoryCombo = ttk.Combobox(width = 15, values = list(category.keys()))
self.CategoryCombo.bind('<<ComboboxSelected>>', self.getUpdateData)
self.CategoryCombo.grid(row = 3,column = 1,padx = 10,pady = 25)
self.YearCombo = ttk.Combobox(width = 15, values = b2)
self.YearCombo.grid(row = 7, column = 1, padx = 10, pady = 25)
self.YearCombo.current(0)
def getMPAN(self):
mpan=self.AccountCombo.get()
year=self.YearCombo.get()
self.destroy()
global params
params=[mpan,year]
w=tk.Button(Application(), text='Submit', command=Application().getMPAN)
w.grid(row=8, column=1)
app = Application()
app.master.title('MPAN Selector')
app.mainloop()
This is my first time posting on the site so I apologise if I'm missing any details. I've seen similar questions but none with solutions for this situation.
Figured out where I was going wrong.
Needed to bring the button inside the createWidgets function in order to correctly get the selected values from the ComboBox.
As to closing the widgets with the buttons command i simply needed to add the following line to the init:
self.master=master
Then in the getMPAN function changing the destroy to:
self.master.destroy()
I'm sure this is relatively sloppy fix but in total this was my code:
b2=[[2018],[2019],[2020],[2021],[2022],[2023],[2024],[2025]]
category = {'home': ['utilities','rent','cable'],
'car': ['gas','oil','repairs'],
'rv':['parks','maintenance','payment']}
params=''
mpan=''
year=''
class Application(tk.Frame):
def __init__(self, master=None, Frame=None):
Frame.__init__(self, master)
self.master=master
super(Application,self).__init__()
self.grid(column = 5,row = 20,padx = 50,pady = 50)
self.createWidgets()
def getUpdateData(self, event):
self.AccountCombo['values'] = category[self.CategoryCombo.get()]
self.AccountCombo.current(0)
def createWidgets(self):
tk.Label(text = 'Area Code:').grid(row = 2,column = 1,padx = 10)
tk.Label(text = 'MPAN:').grid(row = 4,column = 1,padx = 10)
tk.Label(text = 'Year:').grid(row = 6, column = 1, padx = 10)
self.AccountCombo = ttk.Combobox( width = 15)
self.AccountCombo.grid(row = 5,column = 1,pady = 25,padx = 10)
self.CategoryCombo = ttk.Combobox(width = 15, values = list(category.keys()))
self.CategoryCombo.bind('<<ComboboxSelected>>', self.getUpdateData)
self.CategoryCombo.grid(row = 3,column = 1,padx = 10,pady = 25)
self.YearCombo = ttk.Combobox(width = 15, values = b2)
self.YearCombo.grid(row = 7, column = 1, padx = 10, pady = 25)
self.YearCombo.current(0)
button=ttk.Button(self, text='Submit', command=self.getMPAN)
button.grid(row=9, column=1)
def getMPAN(self):
mpan=self.AccountCombo.get()
year=self.YearCombo.get()
self.master.destroy()
global params
params=[mpan,year]
w=tk.Button(Application(), text='Submit', command=Application().getMPAN)
w.grid(row=8, column=1)
app = Application()
app.master.title('MPAN Selector')
app.mainloop()
I am writing a programm in which I am trying to open a n number of windows. My code is:
from tkinter import *
from tkinter import ttk
class Main_window(ttk.Frame):
"""A program"""
def __init__(self, master):
ttk.Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
"""Creates all the objects in the window"""
self.min_lbl = ttk.Label(self, text = "1").grid(row = 0, column = 0,
sticky = W)
self.max_lbl = ttk.Label(self, text = "100").grid(row = 0, column = 2,
sticky = W)
spinval = IntVar()
self.scale = ttk.Scale(self, orient = HORIZONTAL,
length = 200,
from_ = 1, to = 100,
variable = spinval,
command=self.accept_whole_number_only)
self.scale.grid(row = 0,column = 1,sticky = W)
self.spinbox = Spinbox(self, from_ = 1, to = 100,
textvariable = spinval,
command = self.update,
width = 10)
self.spinbox.grid(row = 0,column =3,sticky = W)
self.go_bttn = ttk.Button(self, text = "Go",
command = self.create_windows
).grid(row = 1, column = 1, sticky = W)
def accept_whole_number_only(self, e=None):
"""Makes the numbers from the scale whole"""
value = self.scale.get()
if int(value) != value:
self.scale.set(round(value))
def update(self):
"""Updates the scale and spinbox"""
self.scale.set(self.spinbox.get())
def create_windows(self):
"""This function will create all the new windows"""
value = self.scale.get()
window_num = value
negative_window_num = 1
while window_num != 0:
root = Tk()
root.title("This is Window "+str(window_num)[:-2]+" of "+str(value)[:-2])
root.geometry("350x200")
app = Window_creator(root)
root.mainloop()
window_num -= 1
class Window_creator(ttk.Frame):
"""makes child windows"""
def __init__(self, master):
ttk.Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
"""creates all the widgets in the window"""
def main():
"""Loops the window"""
root = Tk()
root.title("Programm")
root.geometry("350x200")
app = Main_window(root)
root.mainloop()
main()
What I want this code to do is I want to be able to set the spinbox or scale to number n and then when I click the Button i want n numbers of child windows to appear. I tried this with a while loop but it doesn't quite work like I want it to by creating a new window just after the I closed the prevoius window. You also have to close the main window first for it to work (I am going to make the button close the window automatically later). Any Ideas on how I could make this work?
Call child = Toplevel(), instead of root = Tk().
Also, you can not call mainloop more than once (since there should be only one event loop).
from tkinter import *
from tkinter import ttk
class Main_window(ttk.Frame):
"""A program"""
def __init__(self, master):
ttk.Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
"""Creates all the objects in the window"""
self.min_lbl = ttk.Label(self, text = "1").grid(row = 0, column = 0,
sticky = W)
self.max_lbl = ttk.Label(self, text = "100").grid(row = 0, column = 2,
sticky = W)
spinval = IntVar()
self.scale = ttk.Scale(self, orient = HORIZONTAL,
length = 200,
from_ = 1, to = 100,
variable = spinval,
command=self.accept_whole_number_only)
self.scale.grid(row = 0,column = 1,sticky = W)
self.spinbox = Spinbox(self, from_ = 1, to = 100,
textvariable = spinval,
command = self.update,
width = 10)
self.spinbox.grid(row = 0,column =3,sticky = W)
self.go_bttn = ttk.Button(self, text = "Go",
command = self.create_windows
).grid(row = 1, column = 1, sticky = W)
def accept_whole_number_only(self, e=None):
"""Makes the numbers from the scale whole"""
value = self.scale.get()
if int(value) != value:
self.scale.set(round(value))
def update(self):
"""Updates the scale and spinbox"""
self.scale.set(self.spinbox.get())
def create_windows(self):
"""This function will create all the new windows"""
value = self.scale.get()
window_num = value
negative_window_num = 1
for n in range(int(window_num)):
child = Toplevel()
child.title("This is Window "+str(window_num)[:-2]+" of "+str(value)[:-2])
child.geometry("350x200")
app = Window_creator(child)
class Window_creator(ttk.Frame):
"""makes child windows"""
def __init__(self, master):
ttk.Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
"""creates all the widgets in the window"""
def main():
"""Loops the window"""
root = Tk()
root.title("Programm")
root.geometry("350x200")
app = Main_window(root)
root.mainloop()
main()