I try to use the ID entry from the GUI to count the similar IDs in the Excel column.
I always get a 0 in the if-loop and red color shows.
But there are similar IDs in the column.
My code
l1 = tk.Label(tab2, text="Status Check")
l1.place(x=10, y=10)
l2 = tk.Label(tab2, text="ID")
l2.place(x=10, y=60)
ID = tk.Entry(tab2)
ID.place(x=80, y=60)
l2 = tk.Label(tab2, text="Status")
l2.place(x=10, y=100)
t1 = tk.Entry(tab2)
t1.place(x=80, y=100)
comment = tk.Label(tab2)
comment.place(x=240, y=100)
df = pd.read_excel(r'Excel.xlsx')
IDlist = df['ID'].tolist()
id = ID.get()
def immunity_check():
d = IDlist.count(id)
print(d)
if d >= 2:
t1.config(bg= "Green")
comment.configure(text="Fully vaccinated!")
elif d == 1:
t1.config(bg= "Yellow")
comment.configure(text="Vaccinated!")
else d <= 0:
t1.config(bg= "Red")
comment.configure(text="Not vaccinated!")
Can anyone give an advice on how to fix it?
I totally agree with furas comment. Thank him, he solved it.
Issue
Currently the code is reading the input from your text-field before button is pressed. Place a print(id) behind the ID.get() statement and watch console, like:
# GUI initialization omitted for brevity
df = pd.read_excel(r'Excel.xlsx') # read from Excel before button-pressed
IDlist = df['ID'].tolist()
id = ID.get() # get input from text-field before button-pressed
print(id)
# wait for a button press
# below is called on button-press and uses previously read id as argument
def immunity_check():
Solution
This is how you could solve it. The id should be read from text-input after button was pressed. So put move statement into the method:
# part 1: GUI initialization omitted for brevity
# part 2: define functions to call later
def read_ids():
df = pd.read_excel(r'Excel.xlsx')
return df['ID'].tolist()
def immunity_check():
id = ID.get() # read the id to search/count
d = id_list.count(id)
print(f"occurrences of id '{id}' in list: {d}")
if d >= 2:
t1.config(bg= "Green")
comment.configure(text="Fully vaccinated!")
elif d == 1:
t1.config(bg= "Yellow")
comment.configure(text="Vaccinated!")
else d <= 0:
t1.config(bg= "Red")
comment.configure(text="Not vaccinated!")
# part 3: main starts
id_list = read_ids()
# add button with trigger to function immunity_check()
button = tk.Button(tab2,text="Check",command=immunity_check) button.place(x=10,y=180)
Related
I read a lot for it and I have the sentiment that there is no solution for me.
Context: user has to enter 6-digit calculation number in the entries. The 9x entries are created by a loop. I wrote the condition to detect if the user did a mistake : number which contains less or more than 6 digit or / and contains a letter. They are working, I tested them. Only 6-digit number are accepted (if 0, it's ok since it means that the user just need to get less than 9x documents).
Goal: if the user did one mistake, a message "Error in the number" at the place of the "0" has to appear right next to the concerned and "faulty" entry.
Everything will be activated through a button.
What I tried: with a list, but it doesn't work.
How can I change the Label dynamically created by the loop ?
user_entries=[]
error_list_length=[0,0,0,0,0,0,0,0,0]
error_list_letters=[0,0,0,0,0,0,0,0,0]
error_calculation_list=[0,0,0,0,0,0,0,0,0]
nbofcalc=9
a=0
b=1
ddd=791250
#------ Function to check if the entered calculation number are composed of 6 characters (mandatory)
def check_calc_number():
global gg_error
gg=0
gg_error=0
while gg<nbofcalc:
if len(user_entries[gg].get()) != 6:
if len(user_entries[gg].get()) ==0:
gg_error+=0
error_list_length[gg]=0
else:
gg_error+=1
error_list_length[gg]=1
else:
gg_error+=0
error_list_length[gg]=0
gg+=1
#------ Function to check if the entered calculation number contains a or many letters (prohibited)
def check_calc_letter():
global hh_error
hh=0
hh_error=0
alphabet_x='a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
for x in range(nbofcalc):
for n in user_entries[hh].get():
if n in alphabet_x:
hh_error+=1
error_list_letters[hh]=1
hh+=1
#------ Function to check with entries has an error and update the list "error_calculation_list" to try to displays the message "Error in the number" next to the concerned entries
def error_length_letters_display():
ww=0
while ww<nbofcalc:
if error_list_length[ww]==1 :
error_calculation_list[ww]="Error"
var_calculation.set(error_calculation_list[ww])
if error_list_letters[ww]==1:
error_calculation_list[ww]="Error"
var_calculation.set(error_calculation_list[ww])
ww+=1
#----- Loop to crate the entries and Label
for x in range(nbofcalc):
cadre1=Frame(fenetre)
cadre1.pack(side=TOP,anchor=NW)
cadre=Frame(cadre1)
cadre.pack()
c=str(b)
calc=Label(cadre,text="Calculation "+c+" ")
calc.pack(side=LEFT)
var_entry=StringVar()
my_entry=Entry(cadre,textvariable=var_entry, bd=5)
my_entry.insert(0,ddd)
my_entry.pack(side=LEFT)
var_calculation=StringVar()
var_calculation.set(error_calculation_list[a])
calc_error_frame=Label(cadre, textvariable=var_calculation) # The Label to change if error
calc_error_frame.pack(side=RIGHT)
user_entries.append(my_entry)
a+=1
b+=1
ddd+=1
Thank you !
You can store values and objects you need to change, so then you can change them dinamically. See this example
from tkinter import *
r = Tk()
my_entries = []
for i in range(5):
e = Label(r, text=i)
my_entries.append(e)
e.pack(side='top')
r.after(4000, lambda: my_entries[2].configure(text='Example'))
r.mainloop()
EDIT 1:As TheLizzard and Cool Cloud pointed out, it's better to avoid using time.sleep() while using tkinter. Replaced with non-blocking after()
you could setup the trace function for tk.StringVar(), when user enter any value into Entry, it will be checked. for example as shown on below user only can type decimal, and you and setup length as well.
def create_widgets(self):
self.vars = tk.StringVar()
self.vars.trace('w', partial(self.validate2, 1, 1))
# Min Voltage Validating Part
self.vars1 = tk.StringVar()
self.vars1.trace('w', partial(self.validate2, 2, 2))
# Max Voltage Validating Part
self.vars2 = tk.StringVar()
self.vars2.trace('w', partial(self.validate2, 3, 4))
# Current Validating Part
self.vars3 = tk.StringVar()
self.vars3.trace('w', partial(self.validate2, 4, 3))
# Channel Validating Part
# function( key, size)
self.enter_info = tk.Label(self, text="Please enter your information: ", bg="lightgrey")
self.enter_info.grid(tke_Table_EnterInfo)
self.voltage = tk.Label(self)
self.voltage["text"] = "MinVoltage"
self.voltage.grid(tke_Label_MinVoltage)
self.voltageInput = tk.Entry(self, width=10, textvariable=self.vars).grid(tke_StringBox_MinVoltage)
self.vars.set(0)
# Min Voltage Validating Part
self.current = tk.Label(self)
self.current["text"] = "MaxVoltage"
self.current.grid(tke_Label_MaxVoltage)
self.currentInput = tk.Entry(self, width=10, textvariable=self.vars1).grid(tke_StringBox_MaxVoltage)
self.vars1.set(5)
# Max Voltage Validating Part
self.power = tk.Label(self)
self.power["text"] = "Current"
self.power.grid(tke_Label_MaxCurrent)
self.powerInput = tk.Entry(self, width=10, textvariable=self.vars2).grid(tke_StringBox_MaxCurrent)
self.vars2.set(62.5)
# Max Current Validating Part
self.channel = tk.Label(self)
self.channel["text"] = "channel"
self.channel.grid(tke_Label_Channel)
self.channelInput = tk.Entry(self, width=10, textvariable=self.vars3).grid(tke_StringBox_Channel)
self.vars3.set(8)
# Max Channel Validating Part
def validate2(self, key, size, *args):
# TODO:add more information
if key == 1:
value = self.vars.get()
elif key == 2:
value = self.vars1.get()
elif key == 3:
value = self.vars2.get()
else:
value = self.vars3.get()
if not value.isdecimal():
print(len(value))
# if len(value) < 2:
corrected = ''.join(filter(str.isdecimal, value))
if key == 1:
self.vars.set(corrected)
elif key == 2:
self.vars1.set(corrected)
elif key == 3:
self.vars2.set(corrected)
else:
self.vars3.set(corrected)
if key == 1:
corrected = self.vars.get()
corrected = corrected[0:size]
self.vars.set(corrected)
elif key == 2:
corrected = self.vars1.get()
corrected = corrected[0:size]
self.vars1.set(corrected)
elif key == 3:
corrected = self.vars2.get()
corrected = corrected[0:size]
self.vars2.set(corrected)
else:
corrected = self.vars3.get()
corrected = corrected[0:size]
self.vars3.set(corrected)
I want to design a Gui script for a NameSort script.
I want to develop a python3 script with Gui. Here is my code for Cli only
text = open('/Users/test/Desktop/readme.txt','r')
def readtxt(txt): #turns txt to ls
dictls=(txt.read()).splitlines()
return dictls
def getdict(dictls): #turns to dictionary
dict1 = {dictls.index(i) : i for i in dictls}
return dict1
def getkey(diction,index): #getkey
return diction[index]
def randomord(x,z): #random order generator, won't generate repeditive numbers
import random
output = []
done = []
y = 0 #already generated
while y <= x:
rnum = random.randint(0,z)
if rnum not in done:
output.append(rnum)
done.append(rnum)
y+=1
return output
def main():
ls=readtxt(text)
while True:
print(f'\nThere are {len(ls)} names on the list.')
try:
h = int(input('Number of names to gen: '))
if h-1 <= len(ls)-1:
outls = [getkey(getdict(ls),i) for i in randomord(h-1,len(ls)-1)]
print('\n'.join(outls))
else:
print(f'[*]ERR: There are only {len(ls)} names on the list.')
except:
print('[*]ERR')
main()
Now I have tried these code
text = open('/root/Desktop/Python/gui/hell.txt','r')
def readtxt(txt): #turns txt to ls
dictls=(txt.read()).splitlines()
return dictls
def getdict(dictls): #turns to dictionary
dict1 = {dictls.index(i) : i for i in dictls}
return dict1
def getkey(diction,index): #getkey
return diction[index]
def randomord(x,z): #random order generator, won't generate repeditive numbers
import random
output = []
done = []
y = 0 #already generated
while y <= x:
rnum = random.randint(0,z)
if rnum not in done:
output.append(rnum)
done.append(rnum)
y+=1
return output
def main():
ls=readtxt(text)
while True:
print(f'\nThere are {len(ls)} names on the list.')
try:
h = int(input('Number of names to gen: '))
if h-1 <= len(ls)-1:
outls = [getkey(getdict(ls),i) for i in randomord(h-1,len(ls)-1)]
print('\n'.join(outls))
else:
print(f'[*]ERR: There are only {len(ls)} names on the list.')
except:
print('[*]ERR')
global startmain
startmain = 0
def test1():
startmain = 1
###########################
##########################
###################################
from tkinter import *
import tkinter as tk
window = tk.Tk()
p1 = tk.Label(
text="Thomas-name-sort",
fg="red",
bg='green',
width=10,
height=8
)
name_ent = tk.Label(text="输入生成数量Number of names to gen:")
entry = tk.Entry()
name_ent.pack()
entry.pack()
name = entry.get()
b1 = tk.Button(
text="auto-testing自检",
bg="blue",
fg="orange",
width=20,
height=5,
command=test1()
)
b1.pack()
if startmain == 1:
main()
#bind-zone
window.mainloop()
It does not work.
I want to design a Gui script for a NameSort script.
I could not bind the button with the function
T have tried "command=main()" and "button.bind("", func=main()"
Please help me!!!
To set a button's function in tkinter, you only pass the function itself in the command parameter i.e.
command = test1,
Not command = test1() as in this case you are just giving it the result of the function (which is None). This is so that it can execute the function each time the button is pressed.
If you want to provide in arguments for it to execute, you'll then have to use a lambda function:
command = lambda: test1(param1, param2),
You can find decent guides on buttons in tkinter here if you're interested
The following code works for requesting input from a user through the Tkinter GUI and turning that input into a usable variable in the main script. However, any value that I put as the last in a list in the if statement (here "4") will hang and crash the program upon enter. This was also the case for "n" in a yes/no scenario. It also happens if I replace the if statement with a while not in [values] - the final value will crash the program. Is this just a quirk of Tkinter or is there something that I am missing?
import tkinter as tk
from tkinter import *
# get choice back from user
global result
badinput = True
while badinput == True:
boxwidth = 1
result = getinput(boxwidth).strip().lower()
if result in ['1', '2', '3', '4']:
badinput = False
# iterate through play options
if result == '1':
# Do Something
elif result =='2':
# Do Something
elif result =='3':
# Do Something
else:
# Do Something
def getinput(boxwidth):
# declaring string variable for storing user input
answer_var = tk.StringVar()
# defining a function that will
# get the answer and set it
def user_response(event):
answer_var.set(answer_entry.get())
return
answer_entry = tk.Entry(root, width = boxwidth, borderwidth = 5)
# making it so that enter calls function
answer_entry.bind('<Return>', user_response)
# placing the entry
answer_entry.pack()
answer_entry.focus()
answer_entry.wait_variable(answer_var)
answer_entry.destroy()
return answer_var.get()
In case anyone is following this question, I did end up solving my problem with a simple if statement within the callback. I can feed a dynamic "choicelist" of acceptable responses into the callback upon user return. If the answer is validated, the gate_var triggers the wait function and sends the program and user response back into the program.
'''
def getinput(boxwidth, choicelist):
# declaring string variable for storing user input
answer_var = tk.StringVar()
gate_var = tk.StringVar()
dumplist = []
# defining a function that will
# get the answer and set it
def user_response(event):
answer_var.set(answer_entry.get())
if choicelist == None:
clearscreen(dumplist)
gate_var.set(answer_entry.get())
return
if answer_var.get() in choicelist:
# passes a validated entry on to gate variable
clearscreen(dumplist)
gate_var.set(answer_entry.get())
else:
# return to entry function and waits if invalid entry
clearscreen(dumplist)
ErrorLabel = tk.Label(root, text = "That is not a valid response.")
ErrorLabel.pack()
ErrorLabel.config(font = ('verdana', 18), bg ='#BE9CCA')
dumplist.append(ErrorLabel)
return
global topentry
if topentry == True:
answer_entry = tk.Entry(top, width = boxwidth, borderwidth = 5)
else:
answer_entry = tk.Entry(root, width = boxwidth, borderwidth = 5)
# making it so that enter calls function
answer_entry.bind('<Return>', user_response)
# placing the entry
answer_entry.pack()
answer_entry.focus()
answer_entry.wait_variable(gate_var)
answer_entry.destroy()
return answer_var.get()
'''
I'm sure the answer to this is obvious but I cannot spot it! I have a very basic quiz(using Tkinter and Python 3) which uses 2 arrays , the question is displayed and then the answer entered is matched using the array index when the submit button is clicked.
The question at index 0 is displayed twice- cannot see why
The score does not increment correctly- even though it is a global variable- it just shows 1 each time.
How can I get the quiz to move to a print statement after the end of the list is reached?
I have tried putting an IF statement in the submit function to check the value of i but cannot get this to work. Can anyone point out my errors please?
from tkinter import *
global questions
questions =["What is the name of the Simpsons' next door neighbour?","What is the name of the school bus driver?",
"Who runs the Kwik-e-mart?","What does Bart do at the end of the opening credits?"]
global answers
answers = [ "Ned Flanders","Otto","Apu","Write On The Blackboard"]
global score
score = 0
global i
i = 0
def submit():
'''runs the submit button'''
global i
global score
question.config(text=questions[i])
if answer.get().lower()==answers[i].lower():
score+=1
else:
score=score
i+=1
scoretxt.config(text =str(score))
answer.delete(0,END)
window = Tk()
window.title("Simpsons Quiz")
window.wm_iconbitmap("homer.ico")
window.configure(background ="#ffd600")
banner = PhotoImage(file ="the-simpsons-banner.gif")
Label(window,image = banner).grid(row = 0,columnspan = 6)
Label(window,text = "Question : ",bg ="#ffd600",justify=LEFT).grid(row = 1,column = 0)
Label(window,text = "Type answer here: ",bg = "#ffd600",justify=LEFT).grid(row = 3, column = 0)
scoreLabel =Label(window,bg = "#ffd600")
scoretxt = Label(window,text ="Your score is: ?",bg = "#ffd600")
scoreLabel.grid(row=5,column = 2)
scoretxt.grid(row = 6,column = 2)
question=Label(window,bg = "white",text= questions[0],justify=LEFT)
question.grid(row =1,column=1)
answer = Entry(window,bg ="white",width = 30)
answer.grid(row = 3,column=1)
# make a submit button
Button(window,text= "Submit",bg = "white",command = submit).grid(row = 3,column = 2)
mainloop()
1) You are printing the question before you increment i. That's why you get twice.
2) It is always 1 becuase of your usage of global. In python you use global keyword in which scope you want to change your variable. Sadly, my english is not good enough to explain this. Please check out these answers.
3) You can use try-except block. I used it there because that is the exact line where you get the error. You can expand its range.
from tkinter import *
questions =["What is the name of the Simpsons' next door neighbour?","What is the name of the school bus driver?",
"Who runs the Kwik-e-mart?","What does Bart do at the end of the opening credits?"]
answers = [ "Ned Flanders","Otto","Apu","Write On The Blackboard"]
#removed globals from here
score = 0
i = 0
def submit():
'''runs the submit button'''
global i
global score
if answer.get().lower()==answers[i].lower():
score+=1
i+=1 #first increment, then show the question since you already show it at startup
try: #since you get the IndexError on this line, I used on here
question.config(text=questions[i])
except IndexError:
print ("something")
scoretxt.config(text = "Your score is: {}".format(str(score)))
answer.delete(0,END)
window = Tk()
window.title("Simpsons Quiz")
window.wm_iconbitmap("homer.ico")
window.configure(background ="#ffd600")
banner = PhotoImage(file ="the-simpsons-banner.gif")
Label(window,image = banner).grid(row = 0,columnspan = 6)
Label(window,text = "Question : ",bg ="#ffd600",justify=LEFT).grid(row = 1,column = 0)
Label(window,text = "Type answer here: ",bg = "#ffd600",justify=LEFT).grid(row = 3, column = 0)
scoreLabel =Label(window,bg = "#ffd600")
scoretxt = Label(window,text ="Your score is: ?",bg = "#ffd600")
scoreLabel.grid(row=5,column = 2)
scoretxt.grid(row = 6,column = 2)
question=Label(window,bg = "white",text= questions[0],justify=LEFT)
question.grid(row =1,column=1)
answer = Entry(window,bg ="white",width = 30)
answer.grid(row = 3,column=1)
# make a submit button
Button(window,text= "Submit",bg = "white",command = submit).grid(row = 3,column = 2)
mainloop()
Also you might want to use a dictionary instead of questions-answers lists.
Hello :) In the typing practice program I am creating in python 3, I have a for...loop that takes the characters from a global list of a certain paragraphs characters and compares it to the character the user is typing.
For some reason, the for loop wont iterate and won't go on to the next character. After some research, I figured out that you have to use local variables in order to do this but that doesn't work either. Here is my code:
import random
from tkinter import *
root=Tk()
a_var = StringVar()
words = []
eachword = []
global eachchar
charlist = []
x=random.randint(0,10)
def typingpractice():
realcharlist = []
something = []
paralist = []
#x=random.randint(0,10)
file = open("groupproject.txt")
line = file.readline()
paraWords = []
for line in file:
newline = line.replace("\n","")
paralist.append(line.replace("\n", ""))
paraWords.append(newline.split(" "))
wordList = []
for c in paraWords[x]:
charlist.append(c)
for b in range(0,len(charlist)):
wordList.append(charlist[b])
#print (wordList)
for p in charlist[b]:
realcharlist.append(p)
#print(realcharlist)
a=Canvas(root, width=500, height=500)
a.pack()
a.create_text(250,50, text = "Typing Fun", width = 500, font = "Verdana", fill = "purple")
a.create_text(250,300, text = paralist[x], width = 500, font = "Times", fill = "purple")
a = Entry(root, width = 100)
a.pack()
a.focus_set()
a["textvariable"] = a_var
def compare(s, realcharlist):
for g in realcharlist:
print ("s:",s)
print ("g:",g)
if s == g:
print ("y")
a['fg'] = 'green'
break
else:
print ("n")
a['fg'] = 'red'
break
def callback(*args):
global s
# print ("b:",xcount)
s = a.get()
s = s[-1:]
compare(s, realcharlist)
a_var.trace_variable("w", callback) #CALL WHEN VARIABLE IS WRITTEN
def practicetest():
print ("nothing here yet")
b = Button(root, text="Start Practice", command=typingpractice)
b.pack()
d = Button(root, text="Test", command=practicetest)
d.pack()
root.mainloop()
The text file "groupproject.txt" is an external text file that contains 10 one-line paragraphs, each character of each paragraph is being compared to what the user is typing in.
Any help on how to make the for loop work would be greatly appreciated. Thanks :D
Basically what happened was there was a break in the for loop so it would always iterate itself starting from 0 again.