having trouble in setting up a calendar in tkinter - python

i have a small ui programm and i need to display a calendar in it or a date picker . (NOTE : userid and password is root")**
i have tried this code :
from Tkinter import *
from PIL import Image, ImageTk
import ttkcalendar
class App():
def __init__(self):
pass
root = Tk()
root.configure(bg='black')
root.attributes('-alpha', 0.0)
def mainWindow(self):
self.root.geometry('{}x{}'.format(600,400))
self.root.attributes('-alpha', 1)
self.root.configure(bg='#404040')
self.ttkcal = ttkcalendar.Calendar(self.root,firstweekday=calendar.SUNDAY)
self.ttkcal.pack()
self.root.wm_title("time sheet management system")
# Create the toolbar as a frame
self.toolbar = Frame(self.root, borderwidth=1, relief='raised')
self.toolbar.configure( bg = '#838383')
# Load all the images first as PNGs and use ImageTk to convert
# them to usable Tkinter images.
self.img1 = Image.open('NewIcon.png')
self.useImg1 = ImageTk.PhotoImage(self.img1)
self.img2 = Image.open('LoadIcon.png')
self.useImg2 = ImageTk.PhotoImage(self.img2)
self.img3 = Image.open('SaveIcon.png')
self.useImg3 = ImageTk.PhotoImage(self.img3)
# Set up all the buttons for use on the toolbars.
newBtn = Button(self.toolbar, image=self.useImg1, command=self.callback)
newBtn.pack(side=LEFT, fill=X)
loadBtn = Button(self.toolbar, image=self.useImg2, command=self.callback)
loadBtn.pack(side=LEFT, fill=X)
saveBtn = Button(self.toolbar, image=self.useImg3, command=self.callback)
saveBtn.pack(side=LEFT, fill=X)
# Add the toolbar
self.toolbar.pack(side=TOP, fill=X)
"""
#create a frame
self.infoArea= Frame(self.root, borderwidth=2,height=40,width=100, relief='raised',bg='red')"""
self.root.mainloop()
"""
# Set up a Text box and scroll bar.
self.scrollbar = Scrollbar(self.root)
self.scrollbar.pack(side=RIGHT, fill=Y)
self.text = Text(self.root)
self.text.pack()
self.text.config(yscrollcommand=self.scrollbar.set)
self.scrollbar.config(command=self.text.yview)"""
def loginClick(self):
self.userid = self.txt1.get()
self.password = self.txt2.get()
print self.userid,self.password
if self.password == 'root' and self.userid == 'root':
self.wi.destroy()
self.mainWindow()
def callback(self):
print "A button was pressed"
def login(self):
self.wi = Toplevel (self.root)
#self.wi.geometry('{}x{}'.format(200,200))
self.wi.configure(bg='#404040')
self.wi.overrideredirect(1)
self.wi.update_idletasks()
self.w = self.wi.winfo_screenwidth()
self.h = self.wi.winfo_screenheight()
self.size = tuple(int(_) for _ in self.wi.geometry().split('+')[0].split('x'))
self.x = self.w/2 - self.size[0]/2
self.y = self.h/2 - self.size[1]/2
self.wi.geometry("%dx%d+%d+%d" % (self.size + (self.x, self.y)))
self.wi.geometry('{}x{}'.format(400,200))
self.frame1 = Frame ( self.wi,bg='#404040' )
self.frame1.pack(side=BOTTOM,fill=X)
self.butt1 = Button(self.frame1,text= "Cancel" , bg = '#838383',fg='white',command = self.wi.destroy)
self.butt1.pack(side=RIGHT,padx=1)
self.butt2 = Button(self.frame1,text= "Login" ,bg = '#838383',fg='white',command = self.loginClick)
self.butt2.pack(side=RIGHT)
"""self.frame2 = Frame ( self.wi,bg='green' )
self.frame2.pack(side=BOTTOM,fill=BOTH)"""
self.lab1 = Label (self.wi,text='UserID',bg='#404040',fg='white')
#self.lab1.pack(side=LEFT,padx=60,pady=20)
self.lab1.place(x=60,y=20)
self.lab2 = Label (self.wi,text='Password',bg='#404040',fg='white')
#self.lab1.pack(side=LEFT,padx=60,pady=20)
self.lab2.place(x=60,y=60)
self.txt1 = Entry( self.wi)
self.txt1.place(x=140,y=20)
self.txt2 = Entry( self.wi,show='*')
self.txt2.place(x=140,y=60)
"""
self.label = Label(self.wi,text="UserID",bg='#838383',fg='white')
self.label.place("""
self.wi.mainloop()
if __name__ == "__main__":
a = App()
#a.root.mainloop()
a.login()
but it is giving error that "name calendar not defined". how can i solve this ?
or is there any other way to implement a calendar or date picker in tkinter.

The code is using calendar module, but it is not importing the module.
self.ttkcal = ttkcalendar.Calendar(self.root, firstweekday=calendar.SUNDAY)
^^^^^^^^^^^^^^^
Simply adding following import statement will solve the problem.
import calendar

Related

How can I detect which on which frame was a Button Clicked in Tkinter?

I have a question. I have this code:
import tkinter as tk
class new_f:
def __init__(self,root,num):
self.new_frame=tk.Frame(root,width=100,height=100,bg='white',bd=3,relief=tk.GROOVE)
self.new_frame.pack(side=tk.LEFT,fill=tk.X,expand=True)
self.num=num
def add_label(self,t):
self.l1=tk.Label(self.new_frame,bg='white',text=t)
self.l1.pack()
def return_instance(self):
return self.num
class Main_win:
def __init__(self,root):
self.root=root
self.bind_number=0
self.current_index=0
self.instance_list=[]
self.b1=tk.Button(self.root,text='Add Frame',command=self.add_frame_win)
self.b1.pack(side=tk.BOTTOM)
self.b2=tk.Button(self.root,text='Add text',command=self.add_text_frame)
self.b2.pack(side=tk.BOTTOM)
def return_instance_num(self,num,*args):
self.current_index=num
def add_frame_win(self):
new_in=new_f(self.root,self.bind_number)
self.instance_list.append(new_in)
new_in.new_frame.bind('<Button-1>',lambda evnt: self.return_instance_num(new_in.return_instance()))
#self.current_index=new_in.return_instance()
self.bind_number+=1
def add_text_frame(self):
instance=self.instance_list[self.current_index]
instance.add_label('Hello World')
root=tk.Tk()
ob=Main_win(root)
root.mainloop()
What I a trying to achieve is that I want to detect on which frame was the left mouse-button clicked so as to make that Frame active and add the labels to that particular Frame. However, I am stuck on how would I go about writing the code. I need a new class Because I don't know how many frames will the user need.
This is a short example of the code I will be implementing later. So my question is:
How will I go to detect which frame was picked so as to make it active to add the labels?
In this approach I have label l1 bound to Button-1
This was achieved by passing self to new_f instead of root
and binding self.l1 to Button-1
import tkinter as tk
class new_f:
def __init__(self, prog, num):
self.prog = prog
self.new_frame = tk.Frame(prog.root, width = 100, height = 100, bg = 'white', bd = 3, relief = tk.GROOVE)
self.new_frame.pack(side = tk.LEFT, fill = tk.X, expand = True)
self.num = num
def add_label(self, t):
self.l1 = tk.Label(self.new_frame, bg = 'white', text = t)
self.l1.pack()
# binding button-1 press to label
self.l1.bind("<Button-1>", lambda evnt: self.prog.return_instance_num(self.return_instance()))
def return_instance(self):
return self.num
class Main_win:
def __init__(self, root):
self.root = root
self.bind_number = 0
self.current_index = 0
self.instance_list = []
self.b1 = tk.Button(self.root, text = 'Add Frame', command = self.add_frame_win)
self.b1.pack(side = tk.BOTTOM)
self.b2 = tk.Button(self.root, text = 'Add text', command = self.add_text_frame)
self.b2.pack(side = tk.BOTTOM)
def return_instance_num(self, num, *args):
self.current_index = num
def add_frame_win(self):
# note passing self not root
new_in = new_f(self, self.bind_number)
self.instance_list.append(new_in)
new_in.new_frame.bind('<Button-1>', lambda evnt: self.return_instance_num(new_in.return_instance()))
#self.current_index = new_in.return_instance()
self.bind_number = self.bind_number + 1
def add_text_frame(self):
instance = self.instance_list[self.current_index]
instance.add_label('Hello World')
root = tk.Tk()
ob = Main_win(root)
# This necessary to prevent error if user hits 'Add text' before 'Add Frame'
ob.add_frame_win()
root.mainloop()
Here is an alternative method that uses dictionaries to store l1 and new_frame objects as keys and new_f instances as values.
This method can be used for other tkinter objects (Entry, Listbox, Text, Canvas)
import tkinter as tk
class new_f:
def __init__(self, parent):
self.parent = parent
self.frame = tk.Frame(
parent.root, width = 100, height = 100,
bg = "white", bd = 3, relief = tk.GROOVE)
self.frame.pack(
side = tk.LEFT, fill = tk.X, expand = True)
self.frame.bind("<Button-1>", parent.get_current_frame)
def add_label(self, t):
self.label = tk.Label(self.frame, bg = "white", text = t)
self.label.pack(fill = tk.BOTH, expand = True)
# bind button-1 to label, set instance_label and current to self
self.label.bind("<Button-1>", self.parent.get_current_label)
self.parent.instance_label[self.label] = self.parent.current = self
class Main_win:
instance_label = dict() # This method can be expanded for other objects
instance_frame = dict() # that you may want to create in frames
def __init__(self, root):
self.root = root
self.b1 = tk.Button(
self.root, text = "Add Frame", command = self.add_frame_win)
self.b1.pack(side = tk.BOTTOM)
self.b2 = tk.Button(
self.root, text = "Add text", command = self.add_text_frame)
self.b2.pack(side = tk.BOTTOM)
def get_current_label(self, ev):
self.current = self.instance_label[ev.widget]
def get_current_frame(self, ev):
self.current = self.instance_frame[ev.widget]
def add_frame_win(self):
# note passing self not root
self.new_in = new_f(self)
self.instance_frame[self.new_in.frame] = self.current = self.new_in
def add_text_frame(self):
# Change message with entry tool?
self.current.add_label("Hello World")
root = tk.Tk()
ob = Main_win(root)
# This necessary to prevent error if user hits 'Add text' before 'Add Frame'
ob.add_frame_win()
root.mainloop()

How do I make python tkinter widgets appear on the right side of a frame and grow left?

Current behavior, adding LabelFrame widgets (with their own label and picture children) into another Labelframe named "Test putting buffs..." The LabelFrame widgets are being added into the left side of the LabelFrame and "grow" to the right. Wanted behavior is for the widgets to appear on the right side of the frame and "grow" left.
Cannot seem to get there with anchor or sticky settings. How can this "grow-left" be done and still preserve the ability to sort by name or time remaining?
Current behavior gif:
Wanted behavior (mocked up with paint):
Code (took out the image stuff so files aren't needed to run):
import tkinter as tk
from tkinter import ttk
from PIL import ImageTk, Image
import time
class MainFrame(tk.Frame):
def __init__(self, container):
super().__init__(container)
self.grid(column=0, row=0)
self.buffs_list_frames = []
self.button1 = ttk.Button(self)
self.button1['text'] = "Simulate frame list appended True Strike"
self.button1['command'] = lambda: self.buffs_frame_list_is_appended(["True Strike", time.time() + 9])
self.button1.grid(column=0, row=0)
self.button2 = ttk.Button(self)
self.button2['text'] = "Simulate frame list appended Bulls"
self.button2['command'] = lambda: self.buffs_frame_list_is_appended(["Bulls", time.time() + 1080])
self.button2.grid(column=0, row=1)
self.button0 = ttk.Button(self)
self.button0['text'] = "Simulate frame list appended Endurance"
self.button0['command'] = lambda: self.buffs_frame_list_is_appended(["Endurance", time.time() + 1080])
self.button0.grid(column=0, row=2)
self.button3 = ttk.Button(self)
self.button3['text'] = "Simulate frame list put into .grid() and displayed"
self.button3['command'] = lambda: self.buffs_display_nicely()
self.button3.grid(column=0, row=3)
self.button4 = ttk.Button(self)
self.button4['text'] = "START loops of time passing"
self.button4['command'] = lambda: self.buffs_loop_time_passing()
self.button4.grid(column=0, row=4)
self.test_label_frame = ttk.LabelFrame(self, text="Testing putting buffs into a frame with grid")
self.test_label_frame.grid(column=1, row=0)
def buffs_loop_time_passing(self):
for x in self.buffs_list_frames:
x.buff_timer.set(f"{x.buff_birthday - time.time():.1f}s")
if x.buff_birthday < time.time() + 6:
x['background'] = 'red'
if x.buff_birthday < time.time():
self.buffs_list_frames.remove(x)
x.destroy()
self.after(1000, self.buffs_loop_time_passing)
def buffs_frame_list_is_appended(self, added_buff):
""" makes the buff frame and adds to the list of frame widgets
"""
self.buff_frame = tk.LabelFrame(self.test_label_frame, borderwidth=1, text=added_buff[0][0:4], labelanchor="n")
# self.buff_frame.buff_image_reference = ImageTk.PhotoImage(Image.open(added_buff[2]))
# self.buff_frame.buff_image_label = ttk.Label(self.buff_frame, image=self.buff_frame.buff_image_reference)
# self.buff_frame.buff_image_label.image_keep = self.buff_frame.buff_image_reference
# self.buff_frame.buff_image_label.grid(column=0, row=0)
self.buff_frame.buff_birthday = added_buff[1]
self.buff_frame.buff_timer = tk.StringVar()
self.buff_frame.buff_timer.set(f"{self.buff_frame.buff_birthday - time.time():.1f}s")
self.buff_frame.buff_label = ttk.Label(self.buff_frame, textvariable=self.buff_frame.buff_timer)
self.buff_frame.buff_label.grid(column=0, row=1)
self.buffs_list_frames.append(self.buff_frame)
self.buffs_display_nicely()
def buffs_display_nicely(self):
""" takes the list of frames, sorts by name, and .grids()s them into the test frame
"""
self.buffs_list_frames = sorted(self.buffs_list_frames, key=lambda z: z['text'])
print(f"sorted? {self.buffs_list_frames}")
j = 0
for x in self.buffs_list_frames:
x.grid(row=0, column=j)
j += 1
class App(tk.Tk):
def __init__(self):
super().__init__()
# configure the root window
self.title('NWN Buff Watcher')
self.geometry('300x50')
if __name__ == "__main__":
app = App()
main_frame = MainFrame(app)
app.mainloop()
Try this (using #acw1668's suggestion):
import tkinter as tk
from tkinter import ttk
from PIL import ImageTk, Image
import time
class MainFrame(tk.Frame):
def __init__(self, container):
super().__init__(container)
self.buffs_list_frames = []
self.buttons_frame = tk.Frame(self)
self.buttons_frame.pack(fill="both", side="left")
self.button1 = ttk.Button(self.buttons_frame, text="Simulate frame list appended True Strike",
command=lambda: self.buffs_frame_list_is_appended("True Strike", 9))
self.button1.grid(column=0, row=0)
self.button2 = ttk.Button(self.buttons_frame, text="Simulate frame list appended Bulls",
command=lambda: self.buffs_frame_list_is_appended("Bulls", 1080))
self.button2.grid(column=0, row=1)
self.button0 = ttk.Button(self.buttons_frame, text="Simulate frame list appended Endurance",
command=lambda: self.buffs_frame_list_is_appended("Endurance", 1080))
self.button0.grid(column=0, row=2)
#self.button3 = ttk.Button(self.buttons_frame, text="Order items", command=self.order_items)
#self.button3.grid(column=0, row=3)
self.button4 = ttk.Button(self.buttons_frame, text="START loops of time passing",
command=self.buffs_loop_time_passing)
self.button4.grid(column=0, row=4)
self.test_label_frame = ttk.LabelFrame(self, text="Testing putting buffs into a frame with grid")
self.test_label_frame.pack(side="right")
def buffs_loop_time_passing(self):
for x in self.buffs_list_frames:
x.buff_timer.set(f"{x.buff_birthday - time.time():.1f}s")
time_now = time.time()
if x.buff_birthday < time_now + 6:
x.config(bg="red")
if x.buff_birthday < time_now:
self.buffs_list_frames.remove(x)
x.destroy()
self.after(100, self.buffs_loop_time_passing)
def buffs_frame_list_is_appended(self, added_buff, time_alive):
""" makes the buff frame and adds to the list of frame widgets
"""
buff_frame = tk.LabelFrame(self.test_label_frame, borderwidth=1,
text=added_buff[:4], labelanchor="n")
# buff_frame.buff_image_reference = ImageTk.PhotoImage(Image.open(added_buff[2]), master=self)
# buff_frame.buff_image_label = ttk.Label(buff_frame, image=buff_frame.buff_image_reference)
# buff_frame.buff_image_label.image_keep = buff_frame.buff_image_reference
# buff_frame.buff_image_label.grid(column=0, row=0)
buff_frame.buff_birthday = time.time() + time_alive
buff_frame.buff_timer = tk.StringVar(master=self)
buff_frame.buff_timer.set(f"{buff_frame.buff_birthday - time.time():.1f}s")
buff_frame.buff_label = ttk.Label(buff_frame,
textvariable=buff_frame.buff_timer)
buff_frame.buff_label.grid(column=0, row=1)
self.buffs_list_frames.append(buff_frame)
self.order_items()
def order_items(self):
self.buffs_list_frames = sorted(self.buffs_list_frames, key=lambda z: z['text'], reverse=True)
for x in self.buffs_list_frames:
x.pack_forget()
x.pack(side="right")
class App(tk.Tk):
def __init__(self):
super().__init__()
# configure the root window
self.title("NWN Buff Watcher")
# self.geometry("300x50")
if __name__ == "__main__":
app = App()
main_frame = MainFrame(app)
main_frame.pack()
app.mainloop()
I made a few changes to your code. The main thing is that I removed buffs_display_nicely and instead added buff_frame.pack(side="right"). The side="right" tells tkinter to add the widgets from the right to the left.
Also you can improve your code by a lot if you add a class instead of using buff_frame.buff_birthday, buff_frame.buff_timer, ... Also it will make your life a lot easier

Text label not showing up

I have changed everything on other answers but nothing works.
from tkinter import *
import tkinter as tk
import tkinter
import pynput
from pynput.keyboard import Key, Listener
from tkinter import filedialog
charCount = 0
keys = []
press_value = 0
root = Tk()
my_menu = Menu(root)
root.config(menu=my_menu)
def label1(root):
label = tkinter.Label(root, text = "correct")
label.pack()
def pressOn():
button_1.configure(fg = "Green", text = "ON")
def pressOff():
button_1.configure(fg = "red", text = "OFF")
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.pack(fill=BOTH, expand=1)
def save_location():
location_window = Tk()
var = StringVar()
var.set('No Folder Selected')
locationLabel = Label(location_window, textvariable=var.get())
locationLabel.place(x=70,y=20)
location_window.update()
def browse_button():
filename = filedialog.askdirectory()
print(filename)
var = filename
button2 = Button(location_window, text="Browse", command=browse_button).grid(row=1, column=0)
location_window.title('Save Location')
location_window.iconbitmap('C:/Users/Gaming/Downloads/floppydisk.ico')
location_window.geometry('250x100')
location_window.mainloop()
file_menu = Menu(my_menu, tearoff=False)
my_menu.add_cascade(label="File", menu=file_menu)
file_menu.add_command(label="New...", command=label1)
file_menu.add_command(label="Exit", command=root.quit)
#Create an edit menu item
edit_menu = Menu(my_menu, tearoff=False)
my_menu.add_cascade(label="Edit", menu=edit_menu)
edit_menu.add_command(label="Save Location", command=save_location)
edit_menu.add_command(label="Copy", command=label1)
def buttonPress():
global press_value
press_value = press_value + 1
if (press_value % 2) == 0:
pressOff()
else:
pressOn()
button_1 = tkinter.Button(text="OFF", width = '10', height = '10', fg = 'red', command = buttonPress)
button_1.pack(side = 'bottom')
If you click 'edit' and then'save location'. It pops up with a box but should show a label about the directory people can choose by picking the browse button. It is not working though, the label is not showing. Thanks for everyone's help in advance.

How to pass the 2D array from one class to another in Tkinter?

I am trying to write my first app using Tkinter. I can't understand at all how it is possible to pass the data on variables in the 2D array (entered by user) from one class to another. Tried to change something, but nothing turned out. I will be very grateful for any help or advice.
from Tkinter import *
date_index = [2017, 2018, 2019, 2020, 2021]
product_name = ['product 1', 'product 2', 'product 3', 'product 4', 'product 5']
class main:
def __init__(self, master):
self.master = master
self.master.title('revenue calc')
Button(self.master, text = 'quantity', command=self.q_button).pack()
Button(self.master, text = 'prices', command=self.p_button).pack()
self.master.mainloop()
def q_button(self):
q_child(self.master)
def p_button(self):
p_child(self.master)
class q_child:
def __init__(self, master):
self.slave = Toplevel(master)
self.slave.title('quantity')
self.corner_frame = Frame(self.slave)
self.corner_frame.grid(row=0, column=0)
self.left_frame = Frame(self.slave)
self.left_frame.grid(row=1, column=0)
self.head_frame = Frame(self.slave)
self.head_frame.grid(row=0, column=1)
self.main_frame = Frame(self.slave)
self.main_frame.grid(row=1, column=1)
self.button_frame = Frame(self.slave)
self.button_frame.grid(row=2, column=1)
for i in range(len(product_name)):
self.testlabel = Label(self.left_frame, text = product_name[i])
self.testlabel.grid(row=i, column=0)
for j in range(len(date_index)):
self.testlabel1 = Label(self.head_frame, width = 5, text = date_index[j])
self.testlabel1.grid(row=0, column=j)
self.q0 = []
for j in range(len(date_index)):
self.q0.append([])
for i in range(len(product_name)):
self.q0[j].append(Entry(self.slave, width = 5, text=""))
self.q0[j][i].grid(row=j, column=i, in_ = self.main_frame)
self.save_q_button = Button(self.button_frame, text = 'save', command = self.save_q_data)
self.save_q_button.pack()
def save_q_data(self):
self.q = []
for j in range(len(date_index)):
self.q.append([])
for i in range(len(product_name)):
self.q[j].append(float(self.q0[j][i].get()))
class p_child:
def __init__(self, master):
self.slave = Toplevel(master)
self.slave.title('prices')
self.corner_frame = Frame(self.slave)
self.corner_frame.grid(row=0, column=0)
self.left_frame = Frame(self.slave)
self.left_frame.grid(row=1, column=0)
self.head_frame = Frame(self.slave)
self.head_frame.grid(row=0, column=1)
self.main_frame = Frame(self.slave)
self.main_frame.grid(row=1, column=1)
self.button_frame = Frame(self.slave)
self.button_frame.grid(row=2, column=1)
for i in range(len(product_name)):
self.testlabel = Label(self.left_frame, text = product_name[i])
self.testlabel.grid(row=i, column=0)
for j in range(len(date_index)):
self.testlabel1 = Label(self.head_frame, width = 5, text = date_index[j])
self.testlabel1.grid(row=0, column=j)
self.p0 = []
for j in range(len(date_index)):
self.p0.append([])
for i in range(len(product_name)):
self.p0[j].append(Entry(self.slave, width = 5, text=""))
self.p0[j][i].grid(row=j, column=i, in_ = self.main_frame)
self.save_p_button = Button(self.button_frame, text = 'save', command = self.save_p_data)
self.save_p_button.pack()
def save_p_data(self):
self.rev = []
self.revall = []
self.p = []
for j in range(len(date_index)):
self.rev.append([])
self.p.append([])
self.s = 0
for i in range(len(product_name)):
self.p[j].append(float(self.p0[j][i].get()))
self.rev[j].append(self.p[j][i]*q[j][i]) # NameError: global name 'q' is not defined
self.s += self.rev[j][i]
self.revall.append(self.s)
root = Tk()
main(root)
See below a simplified version of your code which shows how to pass data (in this case the text of a single Entry box) from your TopLevel() window back to your main window.
Basically, in your q_child class, you store the data you want to return in an attribute called, for example, self.data, so that when you return to the main class, you can access it by calling q.data.
You can even store this data in the main window's master attribute under a name like q_data, so that it can be accessed in the p_child class, through master.q_data
import Tkinter as tk
class main:
def __init__(self, master):
self.master = master
self.master.q_data = "No data entered"
tk.Button(self.master, text='quantity', command=self.q_button).pack()
tk.Button(self.master, text='prices', command=self.p_button).pack()
self.master.mainloop()
def q_button(self):
# Create a TopLevel window to get user input
q = q_child(self.master)
# Wait for the user to close the TopLevel window
self.master.wait_window(q.slave)
# Store the data input by the user in the main window's "master" attribute
self.master.q_data = q.data
def p_button(self):
# Create a TopLevel window to use the user input data
p = p_child(self.master)
# Wait for the user to close the TopLevel window
self.master.wait_window(p.slave)
class q_child:
def __init__(self, master):
# Create a TopLevel window, and grab focus
self.slave = tk.Toplevel(master)
self.slave.grab_set()
# Add an Entry box and a button
self.q_entry = tk.Entry(self.slave, text="")
self.q_entry.pack()
tk.Button(self.slave, text='save', command=self.save_q_data).pack()
# Initialize the data to be returned
self.data = "No data entered"
def save_q_data(self):
# Update the data to be returned with the Entry box content
self.data = self.q_entry.get()
# Close the TopLevel window
self.slave.destroy()
class p_child:
def __init__(self, master):
# Create a TopLevel window, and grab focus
self.slave = tk.Toplevel(master)
self.slave.grab_set()
# Retrieve the user-input data from the "master"
q_data = master.q_data
# Show the data on a label
tk.Label(self.slave, text=q_data).pack()
# Add a button to go back
tk.Button(self.slave, text='back', command=self.slave.destroy).pack()
root = tk.Tk()
main(root)
Important: self.master.wait_window(q.slave) ensures that the main class waits for the TopLevel window to be closed before continuing to run.

Tkinter does not show one frame

I am trying to make a GUI for my program but I have changed my code a lot and I saw that GUI misses one frame but it was fine before.
Could anyone help me and tell why a frame with a button does not appear on the bottom?
Whole "button_part" object does not appear.
from tkinter import *
import tkinter as tk
import os
import glob
BOUNDS = ["Last week", "Last 2 weeks", "Last 3 weeks"]
class settings_part:
path_to_copy = 0
def __init__(self, master, update_func):
path_to_copy = StringVar()
settings_frame = Frame(master, background="")
settings_frame.pack(side=TOP, fill=X)
date_bound = StringVar()
date_bound.set(BOUNDS[1])
date_option = OptionMenu(settings_frame, date_bound, *BOUNDS, command=update_func)
date_option.config(background="#732c30")
date_option.config(foreground="white")
date_option.config(bd=0)
date_option.pack(side=LEFT, padx=5, pady=5)
path_to_copy.set("~/Python/usun")
box_with_path = Entry(settings_frame, textvariable=path_to_copy)
box_with_path.pack(side=RIGHT, padx=5, pady=5)
# s = path_to_copy.get()
class songs_part:
def __init__(self, master, root):
self.songs_frame = Frame(master)
self.update_songs(root.list_of_songs)
self.songs_frame.pack()
def update_songs(self, l):
for song in l:
c = Checkbutton(self.songs_frame, text=song[0], variable=song[1])
c.pack()
class button_part:
def __init__(self, master, copyFunc):
self.button_frame = Frame(master)
btn_image = PhotoImage(file="copybtn.png")
self.copy_button = Button(self.button_frame, command=copyFunc, text="Copy",
image=btn_image, highlightthickness=0, bd=0, activebackground="#732c30")
self.copy_button.pack()
class App:
def __init__(self):
root = Tk()
root.title("Copying songs")
root.geometry("500x500")
root.option_add("*Font", "Calibra")
back_image = PhotoImage(file="back.png")
self.window = Label(root, image=back_image)
self.window.pack(fill="both", expand="yes")
self.list_of_songs = list()
self.make_list_of_songs()
self.set_part = settings_part(self.window, self.update_list)
self.son_part = songs_part(self.window, self)
self.but_part = button_part(self.window, self.copy_songs)
root.mainloop()
def make_list_of_songs(self):
owd = os.getcwd()
os.chdir("/home/stanek/Music/usun")
for file in glob.glob("*.mp3"):
self.list_of_songs.append([file, tk.IntVar()])
os.chdir(owd)
def copy_songs(self):
for s in self.list_of_songs:
print(s)
def update_list(self, arg):
print("updating list with songs from " + arg)
self.son_part = songs_part(self.window, self)
if __name__ == '__main__':
App()
You never pack the button frame.

Categories