Customtkinter: why does this event.widget lose the proper grid information? - python

In an UI I'm trying to make I want to make an interactive matrix where some data should be entered by the user. Apart from the data value Entries, each column and row has an Entry with a placeholder text where the user should enter the name of the column (e.g. price) and row (e.g. a company). In order to generate the matrix I have this class method
import customtkinter as ctk
from tkinter import messagebox
class AK_Matrix_Frame(ctk.CTkFrame):
def __init__(self, root):
#initialize the frame class-------------------
super().__init__(root)
#Set frame properties-------------------------
self.width = 200
self.height = 400
self.grid(row=1, column=0, padx=10, pady=5)
#Parameters-----------------------------------
self.m = 2
self.n = 3
#initialize and set up reference dict----------
self.AK_Widget_Matrix_dict ={}
self.gen_matrix()
#Base Button-----------------------------------
read_button = ctk.CTkButton(self, text = "Read", command = self.read_matrix)
read_button.pack(pady=12, padx = 10)
root.mainloop()
def gen_matrix(self):
matrix_label = ctk.CTkLabel(self, text = "Anbieter-Kategorien Matrix", font= ('Ariel', 18))
matrix_label.pack(pady=12, padx = 10)
self.matrix_frame = ctk.CTkFrame(self, width=200, height=200)
self.matrix_frame.pack( padx=10, pady=5, expand=True)
self.AK_Widget_Matrix_dict[(0,0)] = ctk.CTkLabel(self.matrix_frame, text = "A\K", font= ('Ariel', 14))
self.AK_Widget_Matrix_dict[(0,0)].grid(row = 0, column = 0, padx = 5, pady = 5, sticky='w'+'e'+'n'+'s')
for i in range(self.m):
self.AK_Widget_Matrix_dict[(i+1,0)] = ctk.CTkEntry(self.matrix_frame, placeholder_text = "Anbieter{a}".format(a = i+1), font= ('Ariel', 14))
self.AK_Widget_Matrix_dict[(i+1,0)].grid(row = i+1, column = 0, padx = 5, pady = 5, sticky='w'+'e'+'n'+'s')
self.AK_Widget_Matrix_dict[(i+1,0)].bind("<Return>", self.replace_matrix_entry_w_label)
for j in range(self.n):
if i == 0:
self.AK_Widget_Matrix_dict[(0,j+1)] = ctk.CTkEntry(self.matrix_frame, placeholder_text = "Kategorie{k}".format(k = j+1), font= ('Ariel', 14))
self.AK_Widget_Matrix_dict[(0,j+1)].grid(row = 0, column = j+1, padx = 5, pady = 5, sticky='w'+'e'+'n'+'s')
self.AK_Widget_Matrix_dict[(0,j+1)].bind("<Return>", self.replace_matrix_entry_w_label)
self.AK_Widget_Matrix_dict[(i+1,j+1)] = ctk.CTkEntry(self.matrix_frame, font= ('Ariel', 14))
self.AK_Widget_Matrix_dict[(i+1,j+1)].grid(row = i+1, column = j+1, padx = 5, pady = 5, sticky='w'+'e'+'n'+'s')
def read_matrix(self):
pass
def replace_matrix_entry_w_label(self, event):
print(event.widget.grid_info())
i = event.widget.grid_info()["row"]
j = event.widget.grid_info()["column"]
print(event.widget)
print("Row, Column:",i,j)
txt = event.widget.get()
print("Event widget contains:",txt)
event.widget.destroy()
self.AK_Widget_Matrix_dict[(i , j)] = ctk.CTkLabel(self.matrix_frame, text = txt, font= ('Ariel', 14))
self.AK_Widget_Matrix_dict[(i , j)].grid(row = i, column = j, padx = 5, pady = 5, sticky='w'+'e'+'n'+'s')
AK_Matrix_Frame(ctk.CTk())
The matrix displays without problem and all entries and labels are placed in the correct location. But when the class method self.replace_matrix_entry_w_label is called, the grid information is transmitted falsely.
And this is the output for any fringe column or row entry I enter text and press return:
{'in': <customtkinter.windows.widgets.ctk_entry.CTkEntry object .!ak_matrix_frame.!ctkframe.!ctkentry2>, 'column': 0, 'row': 0, 'columnspan': 1, 'rowspan': 1, 'ipadx': 0, 'ipady': 0, 'padx': 6, 'pady': (2, 3), 'sticky': 'nesw'}
Row, Column: 0 0
Event widget contains: 23def
So the text one writes in is read correctly, but the row and column are wrong (always 0,0 no matter where the widget is located).
I had the code almost identically with tkinter instead off customtkinter, and then it worked.
Why is the row and column in grid_info() not correct?
I tried accessing the bound widgets event.widget.grid_info() in order to get row and column position and use that to replace the Entry with a Label. What actually happens is that the row and column values are always 0,0, no matter which entry in the matrix I select. Since the text written in the Entry is actually correct I don't understand where the problem is.

The problem arises because customtkinter's CTkEntry widget internally creates a tkinter Entry as an attribute of itself.
event.widget does not refer to the CTkEntry that has a row and column number in your grid, but instead refers to the Entry that this CTkEntry contains.
Your code in the function replace_matrix_entry_w_label asks for the position of Entry in its parent. But the parent is a CTkEntry widget and the only location is (0,0). The code works if you ask for the grid_info() of the master of Entry, that is of CTkEntry. Like this:
def replace_matrix_entry_w_label(self, event):
i = event.widget.master.grid_info()["row"]
j = event.widget.master.grid_info()["column"]
print("Row, Column:",i,j)
txt = event.widget.get()
event.widget.master.destroy()
self.AK_Widget_Matrix_dict[(i , j)] = ctk.CTkLabel(self.matrix_frame, text = txt, font= ('Ariel', 14))
self.AK_Widget_Matrix_dict[(i , j)].grid(row = i, column = j, padx = 5, pady = 5, sticky='w'+'e'+'n'+'s')
For the same reason as described above, if you don't destroy event.widget.master you will still have an empty shell of CTkEntry where just the internal Entry is destroyed, but the object still lives on your UI.

Related

Need to get the multi-digit integer Entry value after the last digit key is pressed

I am relatively new to tkinter, and very new to coding with classes. My GUI will have a step that asks user to enter in an integer with any number of digits to an Entry(). After the last digit keypress (no keypress in 2000 ms) another function will activate that uses the integer entered. It seems very simple but I cannot seem to get this right. I haven't figured out the .after() part, for now I am just using a binding on the ENTER key. Details on the problems, then the code below. I feel like I am struggling way too much on something that can't be that difficult. Please help.
(Some?) Details:
I am getting a bunch of errors leading up to entry input, regarding 'val' not being defined, despite it being defined.
Pressing ENTER does not result in any return value (I added a print command to the mouse clicks just to see if 'val' was being assigned)
Losing sleep from trying to apply after() function
Code (I tried to strip down to essentials best I could, my problem is near the bottom):
'''
import tkinter as tk
import tkinter.messagebox
kk = 1
class App(tk.Tk):
WIDTH = 1000
HEIGHT = 520
def __init__(self):
super().__init__()
self.geometry(f"{App.WIDTH}x{App.HEIGHT}")
self.protocol("WM_DELETE_WINDOW", self.on_closing) # call .on_closing() when app gets closed
self.fr0 = tk.Frame(master=self, background = 'grey')
self.fr0.pack(fill = 'both', expand = True, padx = 20, pady = 20)
# configure grid layout (2x1)
self.fr0.columnconfigure(0, weight = 1)
self.fr0.columnconfigure(1, weight = 1)
self.fr0.rowconfigure((1,2,3), weight = 1)
# Title
self.lab_bcwt = tk.Label(self.fr0, text = 'Title', font=("Roboto Medium", 40), justify = 'center')
self.lab_bcwt.grid(row = 0,rowspan = 2, columnspan = 2)
# ===============================
self.fr1 = tk.Frame(self.fr0)#, fg_color=("black","grey"))
self.fr1.grid(row=2, rowspan = 2, columnspan = 2, sticky = 'nsew', padx = 10, pady = 10)
self.fr1.columnconfigure(0, weight = 1)
self.fr1.columnconfigure(1, weight = 1)
self.fr1.rowconfigure((0,1,2,3,4,5), weight = 1)
# ===============================
self.fr2 = tk.Frame(self.fr1)
self.fr2.grid(row=0, columnspan = 2, sticky = 'new', padx = 10, pady = 10)
self.fr2.grid_rowconfigure(0, weight = 1)
self.fr2.grid_columnconfigure(0, weight = 1)
# ===============================
self.lab1 = tk.Label(self.fr2, text = 'This text appears first\n (click to continue)', font=("Ariel", -22), justify = 'center')
self.lab1.grid( row = 0, columnspan = 2, padx = 10, pady = 5)
self.bind("<Button-1>",self.click)
def on_closing(self, event=0):
self.destroy()
def exmp_gps(self):
self.lab1.destroy()
self.lab2 = tk.Label(self.fr2, text = 'Then this text appears second,\n telling you to input an integer', font=('Ariel', -22))
self.lab2.grid(row = 0, column = 0, sticky = 'new', padx = 10, pady = 10)
self.lab3 = tk.Label(self.fr1, text = 'Any Integer', borderwidth = 2, font = ('Ariel', 12))
self.lab3.grid(row = 1, column = 0, sticky = 'ne', padx = 10)
self.entry1 = tk.Entry(self.fr1, text = 'any integer', justify = 'center')
self.entry1.grid(row = 1, column = 1, sticky = 'nw',padx = 10)
self.entry1.configure(font = ('Arial Rounded MT Bold', 13))
def key_pressed(event):
global val
val = int(self.entry1.get())
# print(val)
self.entry1.bind("<KeyRelease>", key_pressed)
# Ideally
self.entry1.bind("<Return>", print(['Function using', val+1]))
def click(self,event):
global kk
if kk == 1:
self.exmp_gps()
if kk > 1:
print(['Function using', val+1])
if __name__ == "__main__":
app = App()
app.mainloop()
'''
There is few problems in code.
bind needs function's name without () but you use print() so it first runs print() (which returns None) and later it binds None to <Return>. You could bind lambda event:print(...) to run print() when you press Enter.
Code could be more readable if you would use normal self.val instead of global val and if normal function in class def key_pressed(self, event): instead of nested function.
Everytime when you click button then it runs clik() and it runs self.exmp_gps() and it creates new Entry. You should increase kk in click() to run self.exmp_gps() only once. And to make it more readable you could use ie. self.visible = False and later set self.visible = True
You think it can be simple to activate function 2000ms after last keypress - but it is not. It would have to use after() and remeber its ID and time when it was created (to delete it if next key will be pressed before 2000ms, and use new after()).
Using Enter is much, much simpler.
Full code with changes.
I added after() but I didn't test it - maybe in some situations it may run function many times.
import tkinter as tk
import tkinter.messagebox
class App(tk.Tk):
WIDTH = 1000
HEIGHT = 520
def __init__(self):
super().__init__()
self.geometry(f"{App.WIDTH}x{App.HEIGHT}")
self.protocol("WM_DELETE_WINDOW", self.on_closing) # call .on_closing() when app gets closed
self.fr0 = tk.Frame(master=self, background='grey')
self.fr0.pack(fill='both', expand=True, padx=20, pady=20)
# configure grid layout (2x1)
self.fr0.columnconfigure(0, weight=1)
self.fr0.columnconfigure(1, weight=1)
self.fr0.rowconfigure((1, 2, 3), weight=1)
# Title
self.lab_bcwt = tk.Label(self.fr0, text='Title', font=("Roboto Medium", 40), justify='center')
self.lab_bcwt.grid(row=0, rowspan=2, columnspan=2)
# ===============================
self.fr1 = tk.Frame(self.fr0)#, fg_color=("black","grey"))
self.fr1.grid(row=2, rowspan=2, columnspan=2, sticky='nsew', padx=10, pady=10)
self.fr1.columnconfigure(0, weight=1)
self.fr1.columnconfigure(1, weight=1)
self.fr1.rowconfigure((0, 1, 2, 3, 4, 5), weight=1)
# ===============================
self.fr2 = tk.Frame(self.fr1)
self.fr2.grid(row=0, columnspan=2, sticky='new', padx=10, pady=10)
self.fr2.grid_rowconfigure(0, weight=1)
self.fr2.grid_columnconfigure(0, weight=1)
# ===============================
self.lab1 = tk.Label(self.fr2, text='This text appears first\n (click to continue)', font=("Ariel", -22), justify='center')
self.lab1.grid(row=0, columnspan=2, padx=10, pady=5)
self.bind("<Button-1>", self.click)
self.val = 0
self.visible = False
self.after_id = None
def on_closing(self, event=0):
self.destroy()
def key_pressed(self, event):
self.val = int(self.entry1.get())
print('[key_pressed]', self.val)
if self.after_id:
print('[key_pressed] cancel after:', self.after_id)
self.after_cancel(self.after_id)
self.after_id = None
self.after_id = self.after(2000, self.process_data)
print('[key_pressed] create after:', self.after_id)
def process_data(self):
print('[process_data]')
def exmp_gps(self):
self.lab1.destroy()
self.lab2 = tk.Label(self.fr2, text='Then this text appears second,\n telling you to input an integer', font=('Ariel', -22))
self.lab2.grid(row=0, column=0, sticky='new', padx=10, pady=10)
self.lab3 = tk.Label(self.fr1, text='Any Integer', borderwidth=2, font=('Ariel', 12))
self.lab3.grid(row=1, column=0, sticky='ne', padx=10)
self.entry1 = tk.Entry(self.fr1, text='any integer', justify='center')
self.entry1.grid(row=1, column=1, sticky='nw', padx=10)
self.entry1.configure(font=('Arial Rounded MT Bold', 13))
self.entry1.bind("<KeyRelease>", self.key_pressed)
self.entry1.bind("<Return>", lambda event:print('[Return] Function using', self.val))
def click(self, event):
if not self.visible:
self.visible = True
self.exmp_gps()
else:
print('[click] Function using', self.val)
if __name__ == "__main__":
app = App()
app.mainloop()

how to format 2 check buttons in same row and column python

I have created two check buttons and I want them both in row 5 and column 1. But I want the 'YES' check button to be formatted on the left side and the 'NO' check button to be on the right.
I have used sticky but it will not work. I also tried changing the width of the check buttons but this did not work either.
Do you have any suggestions?
Thank you!
self.yes_checkbtn = Checkbutton(self.entry_frame, width = 20, variable = checkbutton1,
anchor = W, text = "YES")
self.no_checkbtn = Checkbutton(self.entry_frame, width = 20, variable = checkbutton2,
anchor = E, text = "NO")
self.yes_checkbtn.grid(row = 5, column = 1, sticky = W)
self.no_checkbtn.grid(row = 5, column = 1, sticky = E)
Outcome:
I dont have enough points yet to show the image without a link - sorry
Put both check buttons under another new frame, then you can grid this new frame to column 1 of row 5, also change option width of Checkbutton to a small number, like 5.
Example code
from tkinter import *
root = Tk()
entry_frame = Frame(root)
entry_frame.grid(row=0, column=0)
for i in range(4):
for j in range(2):
label = Label(entry_frame, text=f'Row {i} Column {j}')
label.grid(row=i, column=j)
frame = Frame(entry_frame)
frame.grid(row=4, column=1)
checkbutton1 = BooleanVar()
checkbutton2 = BooleanVar()
yes_checkbtn = Checkbutton(frame, width = 5, variable = checkbutton1,
anchor = W, text = "YES", bg='green')
no_checkbtn = Checkbutton(frame, width = 5, variable = checkbutton2,
anchor = E, text = "NO", bg='blue')
yes_checkbtn.grid(row = 0, column = 1, sticky = W)
no_checkbtn.grid(row = 0, column = 2, sticky = W)
root.mainloop()

Python GUI only shows one label instead of two

So I'm making a game and I was wondering why the num of rows/columns show one instead of showing both. When I comment one out, the other shows and vice versa instead of both showing.
class OthelloGUI():
def __init__(self):
self._root_window = tkinter.Tk()
self._root_window.title('Othello')
self.read_row()
self.read_column()
def read_row(self) -> int:
self.row_text =tkinter.StringVar()
self.row_text.set('Num of rows:')
row_label = tkinter.Label(
master = self._root_window, textvariable = self.row_text,
background = 'yellow', height = 1, width = 10, font = DEFAULT_FONT)
row_label.grid(row=1, column = 0, padx = 10, pady=10, sticky = tkinter.W+tkinter.N)
return self.row.get()
def read_column(self) -> int:
self.column_text =tkinter.StringVar()
self.column_text.set('Num of columns:')
column_label = tkinter.Label(
master = self._root_window, textvariable = self.column_text,
background = 'yellow', height = 1, width = 13, font = DEFAULT_FONT)
column_label.grid(row=1, column = 0, padx = 10, pady=50, sticky = tkinter.W+tkinter.N)
return self.column.get()
You are calling grid with the same coordinates:
row_label.grid(row=1, column = 0, padx = 10, pady=10, sticky = tkinter.W+tkinter.N)
column_label.grid(row=1, column = 0, padx = 10, pady=50, sticky = tkinter.W+tkinter.N)
When you grid both at (1, 0), the second one will override the first. Instead, use different row/column arguments:
row_label.grid(row=1, column = 0, padx = 10, pady=10, sticky = tkinter.W+tkinter.N)
column_label.grid(row=2, column = 0, padx = 10, pady=50, sticky = tkinter.W+tkinter.N)
Of course, set the row/column to whatever you want in your interface.

'NoneType' Issues with tkinter [duplicate]

This question already has answers here:
Tkinter: AttributeError: NoneType object has no attribute <attribute name>
(4 answers)
Closed 7 years ago.
So I'm trying to write some code that takes two user inputted values, compares them, and then tells the user if he/she input the correct values. (USL should be greater than LSL, pretty simple criteria) Here you can see how i get the entry from the user
# get USL and LSL
Label(self, text = "USL").grid(row = 5, column = 0, sticky = W, padx=5, pady=5)
self.e6 = Entry(self).grid(row = 5, column = 1)
Label(self, text = "LSL").grid(row = 6, column = 0, sticky = W, padx=5, pady=5)
self.e7 = Entry(self).grid(row = 6, column = 1)
This next bit of code is where I check the code
# button to check USL is higher than LSL
self.button = Button(self)
self.button["text"] = "Check USL and LSL"
self.button["command"] = self.check_limits
self.button.grid(row = 6, column = 2, sticky = W, padx=5, pady=5)
and finally here is where i define the check_limits function
def check_limits(self):
e6 = int(self.e6)
e7 = int(self.e7)
if e6 > e7:
message = "Limits are good"
else:
message = "USL can't be less than LSL, please re-enter USL and LSL"
self.text.delete(0.0, END)
self.text.insert(0.0, message)
Currently I have the variables e6 and e7 forced as integers, but when i do this I get an error saying that int() arguments must be a string or a number, not "NoneType". Why would they be defined as null and not integers in this case?
Alternatively, if I don't force them to be integers then I always get "USL can't be less than...", regardless of whether e6 is greater or less than e7. Why is it doing this and how do I fix it?
Here's my entire code if any else of it is needed for the context of this question
from Tkinter import *
class Application(Frame):
""" A SPC program that takes user input and saves the file """
def __init__(self,master):
""" initializes the frame """
Frame.__init__(self,master)
self.grid()
self.create_widgets()
def create_widgets(self):
"""create widgets for user inputted data"""
# get name
Label(self, text = "First Name").grid(row = 0, column = 0, sticky = W, padx=5, pady=5)
self.e1 = Entry(self).grid(row = 0, column = 1)
Label(self, text = "Last Name").grid(row = 1, column = 0, sticky = W, padx=5, pady=5)
self.e2 = Entry(self).grid(row = 1, column = 1)
# get work order
Label(self, text = "Work Order Number").grid(row = 2, column = 0, sticky = W, padx=5, pady=5)
self.e3 = Entry(self).grid(row = 2, column = 1)
# get todays date
Label(self, text = "Todays Date").grid(row = 3, column = 0, sticky = W, padx=5, pady=5)
self.e4 = Entry(self).grid(row = 3, column = 1)
# get bubble number
Label(self, text = "Bubble Number").grid(row = 4, column = 0, sticky = W, padx=5, pady=5)
self.e5 = Entry(self).grid(row = 4, column = 1)
# get USL and LSL
Label(self, text = "USL").grid(row = 5, column = 0, sticky = W, padx=5, pady=5)
self.e6 = Entry(self).grid(row = 5, column = 1)
Label(self, text = "LSL").grid(row = 6, column = 0, sticky = W, padx=5, pady=5)
self.e7 = Entry(self).grid(row = 6, column = 1)
# button to check USL is higher than LSL
self.button = Button(self)
self.button["text"] = "Check USL and LSL"
self.button["command"] = self.check_limits
self.button.grid(row = 6, column = 2, sticky = W, padx=5, pady=5)
# creates a spot to dictate whether USL and LSL are correct
self.text = Text(self, width = 35, height = 2, wrap = WORD)
self.text.grid(row = 6, column = 3, sticky = W)
def check_limits(self):
e6 = int(self.e6)
e7 = int(self.e7)
if e6 > e7:
message = "Limits are good"
else:
message = "USL can't be less than LSL, please re-enter USL and LSL"
self.text.delete(0.0, END)
self.text.insert(0.0, message)
root = Tk()
root.title("SPC Input Program")
root.geometry("700x500")
app = Application(root)
root.mainloop()
Your issue is this
self.e6 = Entry(self).grid(row = 5, column = 1)
When you want to use an assigned widget you can't pack, place or grid it. You need to change it to this
self.e6 = Entry(self)
self.e6.grid(row = 5, column = 1)
You are getting NoneType because of the assignment with the grid. Doing that is fine for static widgets like Labels and Buttons you don't plan on accessing. But when you want to get or assign a value to the widget, it needs to be the widget itself and not widget.grid()

Can't insert a user input value because "str object has no attribute get" in tkinter

So several other people have asked similar questions, but I don't think they necessarily apply to my situation. I'm writing a program that's eventually going to take user inputs, check to make sure they correct, and then save it all to a file. Currently, I'm passing all the user inputs to a text box in tkinter so that I can just save whatever's in that one text box. I'm using a for loop to go through the 7 user entry fields I have and then insert them into the text box.
def submit(self):
""" submits user data up to input data section of GUI and checks USL vs LSL"""
e6 = IntVar(self.e6)
e7 = IntVar(self.e7)
if e6 > e7:
message = "Limits are good"
else:
message = "USL can't be less than LSL, please re-enter USL and LSL"
self.checklimits.delete(0.0, END)
self.checklimits.insert(0.0, message)
x = 1
for x in range (1, 8):
xname = "self.e" + str(x)
entry = xname.get()
if entry:
self.checktext.insert(END, entry + "\n")
x = x+1
I'm wanting to take the x value in the for loop and eventually end up with something like "self.e#.get()" since that's how i've defined the user entries, see example below:
def create_widgets(self):
"""create widgets for user inputted data"""
# creates a text widget next to the entries that displays what the user has input
Label(self, text = "Do these values you entered seem correct?").grid(row = 0, column = 4, sticky = W, padx = 5, pady = 5)
self.checktext = Text(self, width =15, height = 42, wrap = WORD)
self.checktext.grid(row = 1, rowspan = 10, column = 4, sticky = W, padx =5, pady =5)
# get name
Label(self, text = "First Name:").grid(row = 0, column = 0, sticky = W, padx=5, pady=5)
self.e1 = Entry(self)
self.e1.grid(row = 0, column = 1)
Label(self, text = "Last Name:").grid(row = 1, column = 0, sticky = W, padx=5, pady=5)
self.e2 = Entry(self)
self.e2.grid(row = 1, column = 1)
Right now though, python isn't recognizing that entry as an entry and is saying back to me that "'str' object has no attribute 'get'"
So for one, why can't I "get" a string value, and two, how can I get python to recognize my previously defined entry? Here's my entire code for context
from Tkinter import *
class Application(Frame):
""" A SPC program that takes user input and saves the file """
def __init__(self,master):
""" initializes the frame """
Frame.__init__(self,master)
self.grid()
self.create_widgets()
def create_widgets(self):
"""create widgets for user inputted data"""
# creates a text widget next to the entries that displays what the user has input
Label(self, text = "Do these values you entered seem correct?").grid(row = 0, column = 4, sticky = W, padx = 5, pady = 5)
self.checktext = Text(self, width =15, height = 42, wrap = WORD)
self.checktext.grid(row = 1, rowspan = 10, column = 4, sticky = W, padx =5, pady =5)
# get name
Label(self, text = "First Name:").grid(row = 0, column = 0, sticky = W, padx=5, pady=5)
self.e1 = Entry(self)
self.e1.grid(row = 0, column = 1)
Label(self, text = "Last Name:").grid(row = 1, column = 0, sticky = W, padx=5, pady=5)
self.e2 = Entry(self)
self.e2.grid(row = 1, column = 1)
# get work order
Label(self, text = "Work Order Number:").grid(row = 2, column = 0, sticky = W, padx=5, pady=5)
self.e3 = Entry(self)
self.e3.grid(row = 2, column = 1)
# get todays date
Label(self, text = "Todays Date:").grid(row = 3, column = 0, sticky = W, padx=5, pady=5)
self.e4 = Entry(self)
self.e4.grid(row = 3, column = 1)
# get bubble number
Label(self, text = "Bubble Number:").grid(row = 4, column = 0, sticky = W, padx=5, pady=5)
self.e5 = Entry(self)
self.e5.grid(row = 4, column = 1)
# get USL and LSL
Label(self, text = "USL:").grid(row = 5, column = 0, sticky = W, padx=5, pady=5)
self.e6 = Entry(self)
self.e6.grid(row = 5, column = 1)
Label(self, text = "LSL:").grid(row = 6, column = 0, sticky = W, padx=5, pady=5)
self.e7 = Entry(self)
self.e7.grid(row = 6, column = 1)
"""# button to check USL is higher than LSL
self.button7 = Button(self)
self.button7["text"] = "Check Limits"
self.button7["command"] = self.check_limits
self.button7.grid(row = 6, column = 2, sticky = W, padx=5, pady=5)"""
# button to submit user entered values up to the input data values portion of the gui
self.button6 = Button(self)
self.button6["text"] = "Submit"
self.button6["command"] = self.submit
self.button6.grid(row = 5, column = 2, sticky = W, padx=5, pady=5)
# creates a spot to dictate whether USL and LSL are correct
self.checklimits = Text(self, width = 20, height = 2, wrap = WORD)
self.checklimits.grid(row = 6, column = 3, sticky = W, padx = 5)
""" #adds a scroll bar to the data input text box
scrollbar = Scrollbar(self)
scrollbar.pack(side=RIGHT, fill=Y) """
# get User Input Data values
Label(self, text = "Enter Results:").grid(row = 7, column = 0, sticky = W, padx=5, pady=5)
self.e8 = Text(self, width = 15, height = 30)
self.e8.grid(row = 7, column = 1)
""" def check_limits(self):
checks to see if the USL is greater than the LSL
e6 = IntVar(self.e6)
e7 = IntVar(self.e7)
if e6 > e7:
message = "Limits are good"
else:
message = "USL can't be less than LSL, please re-enter USL and LSL"
self.checklimits.delete(0.0, END)
self.checklimits.insert(0.0, message)"""
def submit(self):
""" submits user data up to input data section of GUI and checks USL vs LSL"""
e6 = IntVar(self.e6)
e7 = IntVar(self.e7)
if e6 > e7:
message = "Limits are good"
else:
message = "USL can't be less than LSL, please re-enter USL and LSL"
self.checklimits.delete(0.0, END)
self.checklimits.insert(0.0, message)
x = 1
for x in range (1, 8):
xname = "self.e" + str(x)
entry = xname.get()
if entry:
self.checktext.insert(END, entry + "\n")
x = x+1
root = Tk()
root.title("SPC Input Program")
root.geometry("700x750")
app = Application(root)
root.mainloop()
It appears that you are assuming that e6 = IntVar(self.e6) is getting the value of an entry widget and converting it to an int. That's not what it's doing. It is creating a new variable named e6 that is initialized to zero, and has self.e6 as the "master".
If you want to get the values from an entry widget and convert it to an integer, use the get method on the entry widget.
e6 = int(self.e6.get())
e7 = int(self.e7.get())
The problem that is causing the "str object has no method get" is this code:
xname = "self.e" + str(x)
entry = xname.get()
This is a terrible way to code. As you can see, it won't work. You can make it work with tricks, but a good rule of thumb is to never try to dynamically create variables like this.
If you want to loop over the entry widgets, put them in a list or tuple. For example:
for widget in (self.e1, self.e2, self.e3, self.e4,
self.e5, self.e6, self.e7, self.e8):
entry = widget.get()
if entry:
self.checktext.insert(END, entry + "\n")
...

Categories