Python Tkinter: object has no attribute tk - python

I am new to tkinter, python, and programming in general. I have made an example program of what I'm trying to do. I am trying to use tkinter GUI to receive user inputs for date and time, then convert these tk entries into strings, then check the format of the date and time strings, then if the format is good add the date and time to a list. My issue is with converting the tk entries into strings. When I try to do so I receive an error that says "Example object has no attribute tk". In my program, I have a tk window that is made in my UserInputWindow function, and I pass this window to PromptDateTime, which is where the user is prompted to enter a date and time. When I try to convert using "dateFromUser = tk.Entry(self)", this is the part that receives the error. I don't understand why the PromptDateTime function had no problem editing the window from UserInputWindow function, yet when tk is directly referenced there is an issue.
Also: I had some trouble with formatting my code below (new to stack overflow) so please note that the first section of code is part of "class Example()", and the second section of code is the main function.
Thank you for your help! Please be nice! I'm a newbie and open to critiques.
class Example():
#data members
__dateEntry = None
__timeEntry = None
exampleList = []
def UserInputWindow(self, windowName, instruction):
#Create new window to display fields and options
new_window = tk.Tk()
new_window.title(f'{windowName}')
new_window.geometry = ("500x500")
#Label to display instructions
label_instruction = Label(new_window, text = (f'{instruction}'), font = ("Courier", 10), justify = LEFT, fg = "black", bg = "light yellow")
label_instruction.grid(row = 0, column = 0)
return new_window
#this function checks to see if date string from user is in proper format, and if it is not an error window appears.
def VerifyDate(self, d):
#code deleted for simplicty for this example
#this function checks to see if time string from user is in proper format, and if it is not an error window appears.
def VerifyTime(self, t):
#code deleted for simplicty for this example
#this function prompts user for date and time
def PromptDateTime(self, new_window):
#Label to display instructions
label_instruction = Label(new_window, text = "Enter activity date and time: ",font = ("Courier", 10), justify = LEFT, fg = "black", bg = "light yellow")
label_instruction.grid(row = 0, column = 0)
#Create labels and entries for date and time
label_date = Label(new_window, text = "Enter date in MM/DD/YYYY format: ",fg = "black", bg = "white")
label_date.grid(row = 1, column = 0, padx = 5)
dateEntry = Entry(new_window, fg = 'black', bg = 'white', width = 10)
dateEntry.grid(row = 2, column = 0, padx = 5)
dateFromUser = tk.Entry(self)
str(dateFromUser)
label_time = Label(new_window, text = "Enter time in hh:mm format (military time): ",fg = "black", bg = "white")
label_time.grid(row = 3, column = 0, padx = 5)
timeEntry = Entry(new_window, fg = 'black', bg = 'white', width = 10)
timeEntry.grid(row = 4, column = 0, padx = 5)
self.VerifyDate(dateFromUser)
self.VerifyTime(timeEntry)
def SubmitButton(self, new_window, new_command):
button_submit = Button(new_window, fg = "black", bg = "light blue", text = "Submit", command = new_command)
button_submit.grid(row = 17, column = 10, pady = 5)
def PromptAndAddToList(self):
window = self.UserInputWindow('Date and Time', 'Enter date and time as specified below.')
self.PromptDateTime(window)
self.SubmitButton(window, lambda:exampleList.append(otherClass(dateEntry, timeEntry)))
#################################################
if __name__ == '__main__':
from tkinter import *
import tkinter as tk
import datetime
ex = Example()
ex.PromptAndAddToList()
root = tk.Tk()
root.withdraw()
root.mainloop()

As the error said, the parent of dateFromUser is Example:
dateFromUser = tk.Entry(self) # self is instance of class Example
but Example is not a tkinter widget.
Use new_window instead of self:
dateFromUser = tk.Entry(new_window)

Related

.exe from tkinter gui does not run (pyinstaller)

Reading a few threads helped me to create a .exe from my tkinter gui.
Unfortunately, nothing happens when I run the .exe file. The code runs normally, when I run it in vsc.
Following the instructions online I did the following steps.
I opened the command prompt, moved to my file location with cd filelocation
I ran the command pyinstaller name-of-my-file.py (also tried with the --onefilespecification for example.)
I get three folders pycache, dist and build, and within build I find the respective .exe file.
As stated above, nothing happens when I run the .exe file. Also tried running it as an administrator.
Just in case, I will publish my code below.
All kinds of help is appreciated.
from tkinter import *
from tkinter import messagebox
import time
import datetime
def clicked(event=None):
t = presentationDuration.get()
try:
t = float(t)
except ValueError:
messagebox.showerror(title='ValueError', message='The string is empty or there is no number entered!')
return
nSpeaker = nextSpeaker.get()
lbl.configure(text = nSpeaker, font = ("Arial Bold", 80))
t = int(t*60)
update(t)
def update(t):
if(t >= 0):
m,s = divmod(t, 60)
left_Time.configure(text = m)
right_Time.configure(text = s)
if(t <= 60):
nSpeaker = nextSpeaker.get()
lbl.configure(text = nSpeaker, bg = 'red', font = ("Arial Bold", 80))
window.after(1000, update, t-1)
window = Tk()
window.title("presenters Toolkit")
lbl_duration = Label(window, text = "duration [mins]")
lbl_duration.grid(column = 0, row = 0)
presentationDuration = Entry(window, width = 10)
presentationDuration.grid(column = 1, row = 0)
lbl_speaker = Label(window, text = "next Speaker")
lbl_speaker.grid(column = 2, row = 0)
nextSpeaker = Entry(window, width = 30)
nextSpeaker.grid(column = 3, row = 0)
lbl = Label(window, text = "", font = ("Arial Bold", 50))
lbl.grid(column = 1, row = 1)
btn = Button(window, text = "start", command = clicked)
btn.grid(column = 1, row = 3)
left_Time = Label(window, text ="--", font = ("Arial Bold", 80))
left_Time.grid(column = 0, row = 4)
mid_Time = Label(window, text = ":", font = ("Arial Bold", 80))
mid_Time.grid(column = 1, row = 4)
right_Time = Label(window, text = "--", font = ("Arial Bold", 80))
right_Time.grid(column = 2, row = 4)
window.mainloop()
You need to move the code of your functions above, so that their code goes, for example, after imports. Also when running your code in the line t = float(presentationDuration.get ()), I found an error related to what if in t = float(presentationDuration.get()) empty, an exception is thrown when the button is clicked ValueError: could not convert string to float. So I would advise you to handle this situation. Below is the code as I would see the clicked function. Sorry for my English, it's not my native language.
def clicked(event=None):
t = presentationDuration.get()
try:
t = float(t)
except ValueError:
messagebox.showerror(title='ValueError', message='The string is empty or there is no number entered!') # also you should have such line in your code `from tkinter import messagebox`
return
nSpeaker = nextSpeaker.get()
lbl.configure(text = nSpeaker, font = ("Arial Bold", 80))
t = int(t*60)
update(t)

How to display output of print() in GUI python

I am new in creating GUI. I am doing it in Python with Tkinter. In my program I calculate following characteristics
def my_myfunction():
my code ...
print("Centroid:", centroid_x, centroid_y)
print("Area:", area)
print("Angle:", angle)
I would like to ask for any help/tips how to display those values in GUI window or how to save them in .txt file so that I can call them in my GUI
Thanks in advance
Tkinter is easy and an easy way to do a GUI, but sometimes it can be frustrating. But you should have read the docs before.
However, you can do in this way.
from tkinter import *
yourData = "My text here"
root = Tk()
frame = Frame(root, width=100, height=100)
frame.pack()
lab = Label(frame,text=yourData)
lab.pack()
root.mainloop()
There are several ways to display the results of any operation in tkiner.
You can use Label, Entry, Text, or even pop up messages boxes. There are some other options but these will probably be what you are looking for.
Take a look at the below example.
I have a simple adding program that will take 2 numbers and add them together. It will display the results in each kind of field you can use as an output in tkinter.
import tkinter as tk
from tkinter import messagebox
class App(tk.Frame):
def __init__(self, master):
self.master = master
lbl1 = tk.Label(self.master, text = "Enter 2 numbers to be added \ntogether and click submit")
lbl1.grid(row = 0, column = 0, columnspan = 3)
self.entry1 = tk.Entry(self.master, width = 5)
self.entry1.grid(row = 1, column = 0)
self.lbl2 = tk.Label(self.master, text = "+")
self.lbl2.grid(row = 1, column = 1)
self.entry2 = tk.Entry(self.master, width = 5)
self.entry2.grid(row = 1, column = 2)
btn1 = tk.Button(self.master, text = "Submit", command = self.add_numbers)
btn1.grid(row = 2, column = 1)
self.lbl3 = tk.Label(self.master, text = "Sum = ")
self.lbl3.grid(row = 3, column = 1)
self.entry3 = tk.Entry(self.master, width = 10)
self.entry3.grid(row = 4, column = 1)
self.text1 = tk.Text(self.master, height = 1, width = 10)
self.text1.grid(row = 5, column = 1)
def add_numbers(self):
x = self.entry1.get()
y = self.entry2.get()
if x != "" and y != "":
sumxy = int(x) + int(y)
self.lbl3.config(text = "Sum = {}".format(sumxy))
self.entry3.delete(0, "end")
self.entry3.insert(0, sumxy)
self.text1.delete(1.0, "end")
self.text1.insert(1.0, sumxy)
messagebox.showinfo("Sum of {} and {}".format(x,y),
"Sum of {} and {} = {}".format(x, y, sumxy))
if __name__ == "__main__":
root = tk.Tk()
myapp = App(root)
root.mainloop()

Python Spin Boxes are copying each other and I don't see why?

I am writing a code to create a time calendar, and for some reason the starting and ending time dials are mirroring each other. I have looked over everything, but I can't see any reason why the code would do such a thing.
Here is the code?
from Tkinter import *
import math
Master = Tk()
def Value_Check():
Start_Hours = eval(Starting_Hours.get())
Start_Min = eval(Starting_Minutes.get())
End_Hours = eval(Ending_Hours.get())
End_Min = eval(Ending_Minutes.get())
Start_Time_Window = ((Start_Hours*60)+ Start_Min)
End_Time_Window = ((End_Hours*60)+ End_Min)
Total_Window = (Start_Time_Window - End_Time_Window)
Window_Hours = math.floor(Total_Window/60)
Window_Minutes = (Total_Window - Window_Hours)
print "You have a ", Window_Hours, "Hours and", Window_Minutes, "minute window to test"
Frame_Start_Window= Frame(Master)
Frame_Start_Window.pack()
#Setting the starting time of the testing window
Start_Time_Frame = Frame(Master)
Start_Time_Frame.pack( side = BOTTOM )
Starting_Title = Label(Frame_Start_Window, text = "When can you start testing? ")
Starting_Title.pack()
Starting_Hours = Spinbox(Frame_Start_Window, text = "Hour", from_ = 1, to = 24, wrap =True, width = 2, command = Value_Check)
Starting_Hours.pack(side = LEFT)
Collen_Title = Label(Frame_Start_Window, text = ":")
Collen_Title.pack(side = LEFT)
Starting_Minutes = Spinbox(Frame_Start_Window, text = "Minutes", from_ = 0, to = 59, wrap =True, width = 2, command = Value_Check)
Starting_Minutes.pack(side = LEFT)
#The end half of the testing window:
Frame_End_Window= Frame(Master)
Frame_End_Window.pack()
#Setting the starting time of the testing window:
End_Title = Label(Frame_End_Window, text = "What time do you HAVE to stop testing?")
End_Title.pack()
Ending_Hours = Spinbox(Frame_End_Window, text = "Hour", from_ = 1, to = 24, wrap =True, width = 2, command = Value_Check)
Ending_Hours.pack(side = LEFT)
Collen2_Title = Label(Frame_End_Window, text = ":")
Collen2_Title.pack(side = LEFT)
Ending_Minutes = Spinbox(Frame_End_Window, text = "Minutes", from_ = 0, to = 59, wrap =True, width = 2, command = Value_Check)
Ending_Minutes.pack(side = LEFT)
#Where the answer from the Test_Calculator button is displayed:
Results_Screen = Text(Master, height=2, width=65)
Results_Screen.pack()
Data_Reset = Button (Master, text = "Reset Values", command = Value_Check)
Data_Reset.pack()
mainloop()
The answer is that Spinbox has no text configuration parameter: It has textvariable, for which it's accepting text as an abbreviation. This means you have two independent Spinbox widgets both using the textvariable of Hour and two independent Spinbox widgets both using the textvariable of Minute. The textvariable setting tells the Spinbox to link the content of the Spinbox to the content of the named variable; any time the Spinbox changes, the named variable will change, and any time the named variable changes, the Spinbox will change. Thus, you change the value in one Spinbox, it updates the variable, which in turn updates the other Spinbox.

Saving variables from entry widgets

I want to have the text input of this entry box save to a list and then be printed. I cannot have it save the input upon the button press and it just prints the placeholder variable.
names = []
from tkinter import*
class Trip:
def __init__(self, parent):
E_name = "q"
self.En_name = "g"
self.En_name = str(self.En_name)
self.go = Frame(parent, width = 500, height = 450, bg = "snow", pady = 30, padx = 10)
self.go.grid(row = 1, column = 0)
self.go.grid_propagate(0) # to reserve space required for frame
self.tet = Frame(parent, width = 500, height = 450, bg = "snow")
name = Label(self.go, text = "Name:", bg = "snow")
name.grid(row = 1, column = 0, sticky = E)
self.E_name = Entry(self.go, width = 40, textvariable = self.En_name)
self.E_name.grid(row = 1, column = 1, sticky = W, pady = 4)
menuButton = Button(self.go, text = "Continue", command = self.breakeverything)
menuButton.grid(row = 8, column = 1, pady = 4)
def breakeverything(self):
names.append(self.En_name)
print (names[0])
self.E_name.delete(0, "end")
#main routine
if __name__ == "__main__":
root = Tk()
root.title("Traveller Details")
play = Trip(root)
root.geometry("500x450+0+0")
root.mainloop()
A textvariable is supposed to be a tkinter.StringVar(), not a primitive string. Your application looks simple enough that it shouldn't even need it. Take out self.En_name, take out the textvariable, and just retrieve the current value of the Entry widget in breakeverything() (which should no longer be an appropriate name):
def breakeverything(self):
names.append(self.E_name.get())
print(names[-1]) # printing the last name in the list seems more useful
self.E_name.delete(0, "end")
I would also recommend moving names into Trip.__init__ and making it an instance variable like everything else, with self.names = []. It'll make it easier to keep track of scopes.
You're using textvariable incorrectly (you must use one of the special Tkinter variables such as StringVar), but you don't need to use it at all. Simply save a reference to the widget, then call the get method when you want the value:
self.E_name = Entry(self.go, width = 40)
...
print("you entered: " + self.E_name.get())
If you insist o using textvariable, use a StringVar and then call the get method on that instead:
self.En_name = StringVar()
self.E_name = Entry(..., textvariable=self.En_name)
...
print("you entered: " + self.En_name.get())

Tkinter destroying a Toplevel

I cannot destroy a Toplevel (Tkinter, python)
In my program
1) in the beginning user presses the button and the toplevel appears
2) inside the toplevel there are some more widgets and one more button
3) when user presses this (second) button, the function (name_of_toplevel.destroy()) start working
4) but then Terminal writes me "NameError: global name 'name_of_toplevel' is not defined"
5) but it really IS defined!
6) buttons are bound with functions with method "bind"
Text of the program:
from Tkinter import *
def Begin(event):
okno.destroy()
def QuitAll(event):
exit(0)
def OpenOkno(event):
#print "<ButtonRelease-1> really works! Horray!"
okno = Toplevel()
okno.title('Question')
okno.geometry('700x300')
Sign = Label(okno,text = 'Quit the program?', font = 'Arial 17')
Sign.grid(row = 2, column = 3)
OK = Button(okno, text = 'YES', bg = 'yellow', fg = 'blue', font = 'Arial 17')
OK.grid(row = 4, column = 2)
OK.bind("<ButtonRelease-1>",QuitAll)
NO = Button(okno, text = 'NO', bg = 'yellow', fg = 'blue', font = 'Arial 17')
NO.grid(row = 4, column = 4)
NO.bind("<ButtonRelease-1>",Begin)
root = Tk() # main window 'program_on_Python'
root.title('Program_on_Python')
root.geometry('400x600')
knpk = Button(root, text = 'click here!', width = 30, height = 5, bg = 'yellow', fg = 'blue', font = 'Arial 17')
knpk.grid(row = 2, column = 2)
knpk.bind("<ButtonRelease-1>",OpenOkno)
root.mainloop()
please, help me, if you can
okno doesn't exist outside of the OpenOkno function, so attempting to access it anywhere else will cause a NameError. One way to address this is to move Begin inside OpenOkno, where the okno object is visible.
def OpenOkno(event):
def Begin(event):
okno.destroy()
#print "<ButtonRelease-1> really works! Horray!"
okno = Toplevel()
#etc... Put rest of function here
You could also use a lambda expression in place of a full function, as an argument to Bind.
NO.bind("<ButtonRelease-1>", lambda event: okno.destroy())
You could also make okno a global variable, so it will be visible everywhere. You would then need to use the global okno statement anywhere you need to assign to okno.
okno = None
def QuitAll(event):
exit(0)
def Begin(event):
okno.destroy()
def OpenOkno(event):
#print "<ButtonRelease-1> really works! Horray!"
global okno
#etc... Put rest of function here

Categories