Python time app, with tkinter not working - python

I tried making a basic time application, but, it doesn't work. If you run it, it displays the gui, the no button works (by closing the window). But, the yes button doesn't create a popup telling you the time.
from tkinter import Tk, Label, Button
from datetime import datetime
LARGE_FONT = ("Verdana", 12)
NORM_FONT = ("Helvetica", 10)
SMALL_FONT = ("Helvetica", 8)
class CurrentTime:
def __init__(self, master):
self.master = master
master.title("Current Time")
self.label = Label(master, text="Do you want to know the current time? Y/N", font=LARGE_FONT)
self.label.pack(side="top", fill="x", pady=10, padx=11)
self.time_button = Button(master, text="Yes", command=self.thetime, font=NORM_FONT)
self.time_button.pack(side="top", fill="x", pady=10, padx=11)
self.close_button = Button(master, text="No", command=master.quit, font=NORM_FONT)
self.close_button.pack(side="top", fill="x", pady=10, padx=11)
def thetime(self, master):
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
master.tile("Current Time")
self.label = Label(master, text="Current Time =", command=current_time, font=LARGE_FONT)
self.label.pack(side="top", fill="x", pady=10)
self.close_button = Button(master, text="Okay", command=master.quit, font=NORM_FONT)
self.close_button.pack(side="top", fill="x", pady=10, padx=11)
root = Tk()
yes = CurrentTime(root)
root.mainloop()
Thank you for your help!

You have extra argument master in def thetime(self, master). Remove the extra argument. Also you do not need to recreate the self.label and self.close_button in the function, just update their text is enough:
def thetime(self):
self.time_button.destroy() # remove the 'Yes' button
current_time = datetime.now().strftime("%H:%M:%S")
self.label.config(text="Current Time = "+current_time) # show the current time
self.close_button.config(text="Okay") # change close_button text to 'Okay'

Related

Tkinter Button does nothing when clicked

This is the code for my personal project, for some reason, I can't get the button to do anything when pressed.
Edit: So I managed to fix the text deleting after each input, so now it will continue to output as many passwords as I want. I removed the 0.0 in output.delete so it doesn't default the text to 0 after each generated password.
from tkinter import *
from datetime import datetime
import pyperclip as pc
def close_window():
window.destroy()
exit()
# Main GUI program
window = Tk()
window.frame()
window.grid_rowconfigure((0, 1), weight=1)
window.grid_columnconfigure((0, 1), weight=1)
window.title("PW Gen")
window.geometry('+10+10')
window.configure(background="black")
Label(window, bg="black", height=0, width=25, font="Raleway").grid(row=1, column=0, sticky=NSEW)
# Enter the last 4 and generate the password
Label(window, text="Enter the last 4 digits of the Reader Name:", bg="black", fg="white", font="Raleway 12 bold").grid(row=1, column=0, sticky=W)
textentry = Entry(window, width=53, bg="white")
textentry.grid(row=2, column=0, sticky=W)
Button(window, text="Generate Password", width=16, font="Raleway 8 bold", command=click).grid(row=3, column=0, sticky=W)
# Output the password
Label(window, text="\nPassword", bg="black", fg="white", font="Raleway 12 bold").grid(row=4, column=0, sticky=W)
output = Text(window, width=40, height=4, wrap=WORD, background="white")
output.grid(row=5, column=0, columnspan=2, sticky=W)
# Button and Text To Quit GUI
Label(window, text="Click to Quit", bg="black", fg="white", font="Raleway 12 bold").grid(row=6, column=0, sticky=W)
Button(window, text="Quit", width=14, font="Raleway 8 bold", command=close_window).grid(row=7, column=0, sticky=W)
window.mainloop()
Not exactly the best solution but you can definitely give it a try.
import tkinter as tk
from datetime import datetime
import string
import pyperclip as pc
import random
root = tk.Tk()
root.title("PW Gen")
root.geometry('+10+10')
mainframe = tk.Frame(root)
text = tk.Text(root, height=5, width=25, font="Raleway")
def pwgen():
last4=text.get('1.0','end')[-5:]
j=[char for char in last4 if char in string.ascii_uppercase or char in string.ascii_lowercase]
print(j)
random.shuffle(j)
print(j)
today = datetime.today()
pw = int(today.strftime("%d")) * int(today.strftime("%m"))
last4=''.join(j)
pwgen = "$ynEL" + str(pw) + str()
pc.copy(pwgen)
print("\nThe password is $ynEL" + str(pw) + str(last4))
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.quit1 = tk.Button(self, text="QUIT", fg="black", command=self.master.destroy)
self.quit1.pack(side="top")
text.pack(side="bottom")
self.b2 = tk.Button(self)
self.create_widgets()
self.pack()
def create_widgets(self):
self.b2["text"] = "GenPW"
self.b2["command"] = pwgen
self.b2.pack(side="left")
def b1(self):
self.b2 = tk.Button(self, text="Generate PW", command=pwgen)
app = Application(root)
root.mainloop()
The code has many problems.
mainframe is not shown and never used.
Text is shown, but never used.
Text is packed inside Application but is not part of Application.
pwgen uses input and no GUI widget. A infinte loop with a GUI application is not good.
You should use the attributes of a datetime directly.
You should not generate the password at two places in the code.
You should not name a local variable like the function.
In Application you are using b1 as method, this method is overloaded by the attribute b1, so you cannot use the method anymore.
In the method b1 you are generating a new butten instead of calling the function pwgen.
import tkinter as tk
from datetime import datetime
import pyperclip as pc
def pwgen():
today = datetime.today()
pw = today.day * today.month
last4 = input("Last 4 of Reader Name [****] ")
password = f"$ynEL{pw}{last4}"
pc.copy(password)
print("\nThe password is", password)
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.quit = tk.Button(self, text="QUIT", fg="black", command=self.master.destroy)
self.quit.pack(side="top")
self.b1 = tk.Button(self, text="GenPW", command=self.click_b1)
self.b1.pack(side="left")
def click_b1(self):
pwgen()
def main():
root = tk.Tk()
root.title("PW Gen")
root.geometry('+10+10')
text = tk.Text(root, height=5, width=25, font="Raleway")
text.pack(side="bottom")
app = Application(master=root)
app.pack()
root.mainloop()
if __name__ == "__main__":
main()
This works. I have used grid manager for more control and removed unused code.
import tkinter as tk
from tkinter import *
from datetime import datetime
import pyperclip as pc
root = tk.Tk()
root.title("PW Gen")
root.geometry('+10+10')
Text = tk.Text(root, height=5, width=25, font="Raleway")
def pwgen():
while True:
today = datetime.today()
pw = int(today.strftime("%d")) * int(today.strftime("%m"))
last4 = input("Last 4 of Reader Name [****] ")
pwgen = "$ynEL" + str(pw) + str(last4)
pc.copy(pwgen)
print("\nThe password is $ynEL" + str(pw) + str(last4))
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.quit = tk.Button(self, text="QUIT", fg="black", command=self.master.destroy)
self.quit.grid(row=0,column=0,sticky=tk.EW)
Text.grid(row=1,column=0,sticky=tk.NSEW)
self.b1 = tk.Button(self, text="Generate PW", command=pwgen)
self.b1.grid(row=0,column=1,sticky=tk.EW)
self.grid(row=0,column=0,sticky=tk.NSEW)
app = Application(master=root)
root.mainloop()
A previous version created multiple Generate PW buttons.

Tkinter button does not appear

I am trying to build a small GUI for my D&D character but my second attack button does not appear.
Tried to make it read as easy as possible. Its my second try on programming, I find the Tkinter really difficult to work with :(
Written in Python 3:
# Tkinter_buildframe #
root = tk.Tk()
frame = tk.Frame(root)
frame.pack( side = TOP )
frame.pack()
root.geometry("300x200")
# This is the charicter stats #
w = Label(root, text="""
charisma modifier = 4
spellcast attack_bonus = 7
""", font="12")
w.pack()
# Quit_button #
button = tk.Button(frame,
text="QUIT",
fg="red",
command=quit)
button.pack(side=tk.BOTTOM)
# Attack1 eldritch_blast_with_hex #
slogan = tk.Button(frame,
text="Eldritch Blast with Hex",
command=eldritch_blast_with_hex)
slogan.pack(side=tk.LEFT)
root.mainloop()
def popupmsg(msg):
popup = tk.Tk()
popup.wm_title("Eldritch Blast with Hex")
label = ttk.Label(popup, text=msg, font=NORM_FONT)
label.pack(side="top", fill="x", pady=10)
B1 = ttk.Button(popup, text="Okay", command = popup.destroy)
B1.pack()
popup.mainloop()
# Attack2 eldritch_blast_without_hex#
slogan = tk.Button(frame,
text="Eldritch Blast without Hex",
command=eldritch_blast_without_hex)
slogan.pack(side=tk.LEFT)
root.mainloop()
def popupmsg(msg):
popup = tk.Tk()
popup.wm_title("Eldritch Blast without Hex")
label = ttk.Label(popup, text=msg, font=NORM_FONT)
label.pack(side="top", fill="x", pady=10)
B1 = ttk.Button(popup, text="Okay", command = popup.destroy)
B1.pack()
You have multiple root.mainloop() in the code, it just pauses the code from continuing the execution of rest of the code. So remove one of the root.mainloop() and place one at the end of the code.

Get the output label of calender toplevel from the master window having "Select Date" button, tkinter

I have a doubt, how to get the top-level value in the master window's label. I mean like i couldn't return the entered value from toplevel window to main's self.
I tried other ways and it didn't work
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
from tkcalendar import Calendar, DateEntry
class Application(tk.Frame):
def _init_(self,master):
Frame._init_(self,master)
self.master=master
self.label=Label(text="",font=("Georgia,12"))
self.label.place(x=50,y=80)
self.create_widgets()
def calendar_view():
def print_sel():
return cal.get()
top = tk.Toplevel(root)
cal = Calendar(top,
font="Arial 14",selectmode='day',
cursor="hand1", year=2020)
cal.pack(fill="both", expand=True)
ttk.Button(top, text="ok", command=print_sel).pack()
root=tk.Tk()
s = ttk.Style(root)
s.theme_use('clam')
root.title("Date")
root.geometry("800x500")
button = tk.Button(root, text = 'Test Start Date', bg='#0073BD',height=1,width=15,padx=5,pady=2, fg="white",command=calendar_view)
button.place(x=500,y=100)
label1 = tk.Label(root, text="<-Click to select Test Start Date", padx=10, pady=10, bg="#e6e9f2", font=("calibri",8))
label1.place(x=630,y=100)
button = tk.Button(root, text = 'Test End Date', bg='#0073BD',height=1,width=15,padx=5,pady=2,fg="white",command=calendar_view)
button.place(x=500,y=150)
label1 = tk.Label(root, text="<-Click to select Test End Date", padx=10, pady=10, bg="#e6e9f2", font=("calibri",8))
label1.place(x=630,y=150)
app=Application(root)
root.configure(bg='#e6e9f2')
root.mainloop()
[here is the reference of the image]1
Suggest to use two StringVar to store the start date and end date, and pass the variable to calendar_view():
def calendar_view(var):
def print_sel():
# update the var
var.set(cal.get_date())
# close the calendar window
top.destroy()
top = tk.Toplevel(root)
cal = Calendar(top, font="Arial 14",selectmode='day',
cursor="hand1", year=2020, date_pattern='y-mm-dd')
cal.pack(fill="both", expand=True)
ttk.Button(top, text="ok", command=print_sel).pack()
# make window a modal window
top.grab_set()
top.wait_window(top)
Then update the creation of the two buttons:
button = tk.Button(root, text = 'Test Start Date', bg='#0073BD',height=1,width=15,padx=5,pady=2, fg="white",
command=lambda: calendar_view(startdate))
button = tk.Button(root, text = 'Test End Date', bg='#0073BD',height=1,width=15,padx=5,pady=2,fg="white",
command=lambda: calendar_view(enddate))
and associate the two variables to the two labels, so that their text are updated whenever the variables are updated:
startdate = tk.StringVar(value="<-Click to select Test Start Date")
label1 = tk.Label(root, textvariable=startdate, padx=10, pady=10, bg="#e6e9f2", font=("calibri",8))
enddate = tk.StringVar(value="<-Click to select Test End Date")
label2 = tk.Label(root, textvariable=enddate, padx=10, pady=10, bg="#e6e9f2", font=("calibri",8))
#acw1668 Here is the updated code, can you send me your version updated code
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
from tkcalendar import Calendar, DateEntry
class Application(tk.Frame):
def _init_(self,master):
Frame._init_(self,master)
self.master=master
self.label=Label(text="",font=("Georgia,12"))
self.label.place(x=50,y=80)
self.create_widgets()
caldate1 = " "
caldate2 = " "
def calendar_view1():
def print_sel1():
global caldate1
caldate1 = cal1.selection_get()
label1.config(text = caldate1)
return caldate1
top1 = tk.Toplevel(root)
cal1 = Calendar(top1,
font="Arial 14",selectmode='day',
cursor="hand2", year=2020)
cal1.pack(fill="both", expand=True)
ttk.Button(top1, text="ok", command=print_sel1).pack()
def calendar_view2():
def print_sel2():
global caldate2
caldate2 = cal2.selection_get()
label2.config(text = caldate2)
return caldate2
top2 = tk.Toplevel(root)
cal2 = Calendar(top2,
font="Arial 14",selectmode='day',
cursor="hand2", year=2020)
cal2.pack(fill="both", expand=True)
ttk.Button(top2, text="ok", command=print_sel2).pack()
root=tk.Tk()
s = ttk.Style(root)
s.theme_use('clam')
root.title("Date")
root.geometry("800x500")
button = tk.Button(root, text = 'Test Start Date', bg='#0073BD',height=1,width=15,padx=5,pady=2, fg="white",command=calendar_view1)
button.place(x=500,y=100)
label1 = tk.Label(root, text="<-Click to select Test Start Date", padx=10, pady=10, bg="#e6e9f2", font=("calibri",8))
label1.place(x=630,y=100)
button = tk.Button(root, text = 'Test End Date', bg='#0073BD',height=1,width=15,padx=5,pady=2,fg="white",command=calendar_view2)
button.place(x=500,y=150)
label2 = tk.Label(root, text="<-Click to select Test End Date", padx=10, pady=10, bg="#e6e9f2", font=("calibri",8))
label2.place(x=630,y=150)
app=Application(root)
root.configure(bg='#e6e9f2')
root.mainloop()

opening a new gui from the gui

updated code as per below comments
I'm struggling to get my top level to open on button press!
I've scanned the code on here but don't seem to be able to get a woking solution. My latest error is:
AttributeError: '_tkinter.tkapp' object has no attribute 'unavail'
from tkinter import *
from ScheduleApi import flightData
import config
from itinerary import fltCreate
class FrontEnd:
def __init__(self, master):
self.master = master
master.title("A simple GUI")
self.label = Label(master, text="This is our first GUI!")
self.label.grid()
self.greet_button = Button(master, text="Create Itinerary", command=self.ItinBuilder)
self.greet_button.grid(row=1)
self.close_button = Button(master, text="Close", command=master.quit)
self.close_button.grid(row=2)
def greet(self):
print("Greetings!")
def ItinBuilder(self):
self = Toplevel(self.master)
self.title ("Please build your itinerary")
self.addflt_button = Button(self.master, text="add flights", command=fltCreate)
self.addflt_button.grid(row=1)
self.addfhtl_button = Button(self.master, text="add hotel", command=self.master.unavail)
self.addflt_button.grid(row=1, column=1)
self.addfmsc_button = Button(self.master, text="add misc item", command=self.master.unavail)
self.addflt_button.grid(row=2, column=1)
self.prvitin_button = Button(self.master, text="preview", command=self.master.unavail)
self.addflt_button.grid(row=2, column=1)
def unavail(self, Toplevel):
print("Function not yet available.")
root = Tk()
my_gui = FrontEnd(root)
root.mainloop()
Please change your function ItinBuilder to this. I hope this is what you expect.
def ItinBuilder(self):
self.newWindow = Toplevel(self.master)
self.newWindow.title ("Please build your itinerary")
self.addflt_button = Button(self.newWindow, text="add flights", command=fltCreate)
self.addflt_button.grid(row=0)
self.addfhtl_button = Button(self.newWindow, text="add hotel", command=self.master.unavail)
self.addfhtl_button.grid(row=0, column=1)
self.addfmsc_button = Button(self.newWindow, text="add misc item", command=self.master.unavail)
self.addfmsc_button.grid(row=1, column=0)
self.prvitin_button = Button(self.newWindow, text="preview", command=self.master.unavail)
self.prvitin_button.grid(row=1, column=1)
The add flights button is in main GUI because you passed the reference to your main window self.master as first argument(called parent in tkinter) in your code.
Only add_flights button is seen and not others because you called grid method only for self.addflt_button and not for other buttons(missed to change variable names in other calls I guess).

Python Tkinter time.sleep()

I am making a program and i have a problem. When using time.sleep() like it shows in the code, i would like it to wait 5 secs after the first label appears and then show the second one, but instead when i press the 'start' button it waits 5 secs and then displays both labels at once. (The code i am interested in is just at the end, in guess_number)
Here's the code:
from tkinter import *
from tkinter import font
from datetime import datetime
import time
class Window(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.master = master
self.master.resizable(0,0)
master.title("Arcade Games")
master.geometry("800x600+560+240")
now = datetime.now()
hour = now.hour
minutes = now.minute
b = Button(self, text="Guess the number", command=self.new_window, cursor='hand2', relief='groove')
b.pack()
self.customFont = font.Font(master, font="Heraldica", size=12)
labelTime = Label(self.master, text=str(hour)+" : "+str(minutes), font=self.customFont)
labelTime.pack(side='bottom')
def new_window(self):
id = "Welcome to the 'Guess your number' game!\nAll you need to do is follow the steps\nand I will guess your number!\n\nClick the button to start!!"
self.window = Toplevel(self.master)
self.window.resizable(0,0)
self.label = Label(self.window, text=id, font=self.customFont)
self.label.pack(side="top", fill="both", padx=20, pady=20)
self.button = Button(self.window, text="Start", relief='groove')
self.button.config(width=20, height=2)
self.button.bind("<Button-1>", self.guess_number)
self.button.pack()
self.window.title("Guess the number")
self.window.geometry("400x300+710+390")
def guess_number(self, event):
self.button.destroy()
self.label.destroy()
labelGuess = Label(self.window, text="Pick any number.\nIt can be 3, 500 or even 1,324,324", font=self.customFont)
labelGuess.pack(padx=20, pady=20)
time.sleep(5)
labelGuess1 = Label(self.window, text="Now double it", font=self.customFont)
labelGuess1.pack(padx=20, pady=20)
if __name__ == "__main__":
root = Tk()
view = Window(root)
view.pack(side="top", fill="both")
root.mainloop()
Any help is appreciated!
Rather than use time.sleep() to stop the main task, try scheduling an event with tkinter's after(), like so:
def guess_number(self, event):
self.button.destroy()
self.label.destroy()
labelGuess = Label(self.window, text="Pick any number.\nIt can be 3, 500 or even 1,324,324", font=self.customFont)
labelGuess.pack(padx=20, pady=20)
self.window.after(5000, self.make_guess1_visible)
def make_guess1_visible(self):
labelGuess1 = Label(self.window, text="Now double it", font=self.customFont)
labelGuess1.pack(padx=20, pady=20)

Categories