For Loop inside Function using a List: not iterating - python

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.

Related

using entry.get in a list count in python

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)

Connect a python script with Tkinter

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

Base 10 Error with passing an int

The error i keep getting is when i try to determine weather the player has enough guesses left to keep playing. i am unable to figure it out does anyone have any idea how to fix this issue please i am stuck.
Also i am a beginner in python and i know there are other easier ways to do this i just do not know how.
here i my error i recieve:
File c: line 68, in initalize_loop
total_guesses = int(total_guesses_left.get())
ValueError: invalid literal for int() with base 10: '[]'
here is my full code below:
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
import random
import os
import sys
#Section the Functions are stored.
def loadWordList(words):
try:
fin = open(words)
for line in fin:
tmp = fin.readline()
wordList.append(tmp.rstrip("\n"))
fin.close
except OSError as err:
print("File Error: ", err, "\n")
exit(1)
def exity():
sys.exit()
def getHint(word, guessed_letter):
#Stores the word in characters in which the player cannot see but still gives the ammount of charaters.
hint = ""
c = 0
while ( c <= (len(word) - 1)):
if word[c] in guessed_letter:
#increments each hint that is correctly guessed unlocking the guessed letter.
hint += word[c]
c += 1
else:
hint += "_"
c +=1
return hint
def countOccurences(word, guess):
c = 0
count = 0
while c <= (len(word)-1):
#Shows the ammount of times the letter occured in that word.
if guess == word[c]:
count +=1
c += 1
else:
c += 1
return count
def get_letter(*args):
guess = inputted_value.get()
guess = guess.lower()
return guess
def valid_guess(guess):
if guess.isalpha() and 1 == len(guess):
return True
else:
user_help.set(invalid_guess)
return False
def final_guess(*args):
finalguess = inputted_value.get()
finalguess = finalguess.lower()
def initalize_loop(*args):
total_guesses = int(total_guesses_left.get())
if ((int(total_guesses > 0)) and (secret_word.get() != word)):
guess = get_letter()
valid = valid_guess(guess)
if valid == True:
if guess in guessed_letter:
invalid_input.set("You have already guessed that letter '{}'".format(guess))
elif guess in word:
invalid_input.set("That is a good guess! '{}' occurs {} time(s) in the secret word.".format(guess, countOccurences(guess, word)))
else:
invalid_input.set("'{}' does not occur in the secret word.".format(guess))
guessed_letter.append(guess)
total_guesses =-1
word_entry.delete(0, 'end')
secret_word_value.set(getHint(word, guesses))
total_guesses_left.set(total_guesses)
print(guessed_letter)
else:
if(secret_word_value.get() == word):
messagebox.showinfo(title= "Winner!", message=("Congradulations! You Correctly guessed the secret word: {}".format(word)))
root.destroy()
else:
finalguess = final_guess()
if finalguess == word:
messagebox.showinfo(frame, title="Congratulations", message= ("Congradulations! You Correctly guessed the secret word: {}".format(word)))
root.destroy()
else:
messagebox.showinfo(title= "Incorrect", message=("Sorry, the secret word was: {} ".format(word)))
root.destroy()
root = Tk()
root.title('COSC 110 Guessing Game' )
frame = ttk.Frame(root, padding = '4 4 15 15')
frame.grid(column=0, row=0, sticky=(N, W, E, S))
inputted_value = StringVar()
user_help = StringVar()
total_guesses_left = StringVar()
secret_word_value = StringVar()
invalid_input = StringVar()
empty = " "
invalid_guess = "Invalid Guess. Please Enter a letter from A-Z"
word_entry= ttk.Entry(frame, width=7)
word_entry.grid(column=2, row=2, sticky=(W, E))
exit_button= ttk.Button(frame, text='Exit', command=exity)
exit_button.grid(column=1, row =7, sticky=(W))
entered_guess = ttk.Label(frame, text='Enter a Letter')
entered_guess.grid(column=1, row=2, sticky=(W, E))
secret_guess = ttk.Label(frame, textvariable=secret_word_value)
secret_guess.grid(column=2, row=1, sticky=(W, E, N, S))
guesses_label= ttk.Label(frame, text='Guesses Remaining:')
guesses_label.grid(column=1, row=3, sticky=(W, E))
total_guesses = ttk.Label(frame, relief ="sunken", textvariable= total_guesses_left)
total_guesses.grid(column=2, row=3, sticky=(W, E))
user_details = ttk.Label(frame, textvariable = user_help)
user_details.grid(column=1, row = 5, sticky=(W, E))
invalid_guesses = ttk.Label(frame, textvariable = invalid_input)
invalid_guesses.grid(column=1, row = 6, sticky =(W, E))
secret_word = ttk.Label(frame, text='Secret Word:')
secret_word.grid(column=1, row=1, sticky=(W, E))
enter_button = ttk.Button(frame, text='Enter', command = initalize_loop)
enter_button.grid(column=3, row =2, sticky=(W, E))
for child in frame.winfo_children():
child.grid_configure(padx=5, pady=5)
enter_button.focus()
enter_button.bind('<Return>', initalize_loop)
if __name__ == "__main__":
if_true = True
while if_true == True:
wordList =[]
loadWordList("Words.txt")
word = random.choice(wordList)
guessed_letter = []
total_guesses = 10
secret_word_value.set(getHint(word, guessed_letter))
total_guesses_left.set(guessed_letter)
invalid_input.set(empty)
user_help.set(empty)
root.mainloop()
if_true = messagebox.askyesno(icon="question", title= "Play Again?", message ="Would you like to play again?")
exit(0)
First you initialize the variable here:
total_guesses_left = StringVar()
Then, inside if __name__ == "__main__": you write:
guessed_letter = []
// ...
total_guesses_left.set(guessed_letter)
So our StringVar instance stored as total_guesses_left gets its value set to an empty list. As it's a StringVar, this leads to a conversion, which means that its internal value now is the string "[]".
Then in your initalize_loop, you try to do
total_guesses = int(total_guesses_left.get())
Of course total_guesses_left.get() will return a string, or more precisely it will return the string "[]".
And as int parses strings representing numbers with a specific base (by default 10), it can only handle strings consisting of alphanumeric characters, and only if they only contain characters used by the specified number base (i.e. by default those are only the characters 0123456789).
Therefore you get the exception that "[]" can not be parsed as int.
You probably want total_guesses_left to store a valid integer representation string and not one of a list.
It means at that moment your total_guesses_left.get() is giving '[]'. base 10 error arises when you try to convert a char or something other than a number which is as a string like
>>> str1='a'
>>> int(str1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'a'
>>> alist='[]'
>>> int(alist)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '[]'
I hope you understand the error. Play around a little with errors. "Trial And Error " :D

Tkinter -- Why won't my button execute a command?

I'm sure I'm missing something laughably obvious, but I've been staring at this for 20 minutes and I have no idea what it is.
class GUI:
def __init__(self):
# creating frame and window
self.winMain = tk.Tk()
self.topFrame = tk.Frame(self.winMain)
self.midFrame = tk.Frame(self.winMain)
self.botFrame = tk.Frame(self.winMain)
# creating labels
self.wordLabel = tk.Label(self.topFrame,text="Word to unscramble",width=18)
self.wordLabel.pack(side="left")
# scrambled word
self.scrambledWord = tk.StringVar()
# open file of scrambled words
dictList = open('dict.txt', 'r')
words = [] # empty list to fill with words
for line in dictList:
words.append(line)
word = random.choice(words)
print(word)
word = ''.join(random.sample(word, len(word)))
self.scrambledWord.set(word)
# label of scrambled word
self.ScWd = tk.Label(self.topFrame, textvariable=self.scrambledWord, width=len(word))
self.ScWd.pack(side="right")
# entry label
self.guessIn = tk.Label(self.midFrame,text="Your guess:", width=15)
self.guessIn.pack(side="left")
# input box
self.guess = tk.Entry(self.midFrame, width=15)
self.guess.pack(side="right")
# guess button
self.guessButton = tk.Button(self.botFrame,text="Guess",command=self.guess)
self.guessButton.pack(side="left")
# status variable
self.stat = tk.StringVar()
# status label
self.status = tk.Label(self.botFrame, textvariable=self.stat,width=10)
self.status.pack(side="right")
self.topFrame.pack(side="top")
self.midFrame.pack()
self.botFrame.pack()
tk.mainloop()
def guess(self):
correct = False
userGuess = self.guess.get()
self.stat.set(userGuess)
if userGuess == self.scrambledWord:
self.stat.set("correct")
correct = True
print(correct)
Sorry for posting the entire thing, but I have no idea where the problem lies. any help is much appreciated.

How to show text on Entry on Tkinter?

I am trying to make a simple calculator with GUI. So what I have so far are the buttons and the Entry box setup but I have no idea how to display text on them. So Currently, the "equation" is equal to 0. What I want to do is when the user presses the equal button, it would display the solved equation to the Entry called inputbox. What will I have to do to display the equation back to the inputbox?
import sys
from Tkinter import *
#modules
equation = '0'
def Entrybox():
theinput = inputbox.get()
if type(theinput) is float:
pass
elif type(theinput) is int:
equation += theinput
else:
return 'Numbers Only'
def bp1():
equation = equation + '1'
def bp2():
equation = equation + '2'
def bp3():
equation = equation + '3'
def bp4():
equation = equation + '4'
def bp5():
equation = equation + '5'
def bp6():
equation = equation + '6'
def bp7():
equation = equation + '7'
def bp8():
equation = equation + '8'
def bp9():
equation = equation + '9'
def bp0():
equation = equation + '0'
def bpplus():
equation = equation + '+'
def bpmin():
equation = equation + '-'
def bpmulti():
equation = equation + '*'
def bpdiv():
equation = equation + '/'
def bpequal():
eval(equation)
return
def bpclear():
equation = equation - equation
gui = Tk()
inputvar = StringVar()
#gui Size
gui.geometry('360x400')
#title
gui.title("A Lucas Calculator")
#The input box
inputbox = Entry(gui, textvariable = inputvar, bd = 10,width = 34)
inputbox.place(x = 40, y = 50)
#buttons
number3 = Button(gui, text = '3',font = 15,width = 4,command = bp3)
number3.place(x = 200,y = 260)
number2 = Button(gui, text = '2',font = 15,width = 4,command = bp2)
number2.place(x = 120,y = 260)
number1 = Button(gui, text = '1',font = 15,width = 4, command = bp1)
number1.place(x = 40,y = 260)
number6 = Button(gui, text = '6',font = 15,width = 4,command = bp6)
number6.place(x = 200,y = 200)
number5 = Button(gui, text = '5',font = 15,width = 4,command = bp5)
number5.place(x = 120 ,y = 200)
number4 = Button(gui, text = '4',font = 15,width = 4,command = bp4)
number4.place(x = 40, y = 200)
number9 = Button(gui, text = '9',font = 15,width = 4, command = bp9)
number9.place(x = 200,y = 140)
number8 = Button(gui, text = '8',font = 15,width = 4,command = bp8)
number8.place(x = 120,y = 140)
number7 = Button(gui, text = '7',font = 15,width = 4,command = bp7)
number7.place(x = 40,y = 140)
number0 = Button(gui, text = "0",font = 15,width = 4,command = bp0)
number0.place(x = 120,y = 318)
signplus = Button(gui, text = "+", font = 14, width = 3,bg = 'red', fg = 'white',command = bpplus)
signplus.place(x = 280,y = 140)
signmin = Button(gui, text = "-", font = 14, width = 3,command = bpmin)
signmin.place(x = 280,y = 200)
signmulti = Button(gui, text = "X", font = 14, width = 3,command = bpmulti)
signmulti.place(x = 280,y = 260)
signdiv = Button(gui, text = "/", font = 14, width = 3,command = bpdiv)
signdiv.place(x = 280,y = 318)
signequal = Button(gui, text = "=", font = 15, width = 4,bg = 'blue',fg = 'white',command = bpequal)
signequal.place(x = 200, y = 318)
clearbutton = Button(gui, text = "Clear", font = 14, width = 4,bg = "green", fg = "white",command = bpclear)
clearbutton.place(x= 40, y = 318)
gui.mainloop()
Since you've already attached a textvariable to the Entry, the easiest thing to do is to use it:
inputvar.set('numbers only')
The tutorial on The Variable Classes in the Tkinter book explains in more detail… but there's really not much more to explain.
(I'm assuming inputvar was properly created as a Tkinter.StringVar() somewhere in the code you haven't shown us, and that you're keeping it around somewhere, like an instance variable, for later use. If not, obviously you'd need to fix those things.)
If you weren't using a textvariable, see the Entry docs for details on other ways to do it.
Unfortunately, your code function as written is too broken to actually get this far.
First, the Entrybox function that you defined never gets called, so nothing you do in that function can possibly have any effect. I'm not sure where you wanted it to get called, so I can't fix that for you.
And there's nowhere you can actually put such a call, because all of your event handler functions will raise an exception as soon as you click them, because they all look like this:
equation = equation + '1'
Whenever you assign to a variable in a function, that means it's a local variable, unless you explicitly say otherwise. But you don't have a local variable named equation until after this assignment finishes—and yet you're trying to use equation + '1' as the value. So, you will get UnboundLocalError: local variable 'equation' referenced before assignment.
You really shouldn't be using global variables in the first place (a GUI frame is one of the paradigm use cases for a class, which is why all of the non-trivial Tkinter examples are written that way, and you should follow those examples). If you really want to use globals, you can, but then you need to be explicit, like this:
def bp1():
global equation
equation = equation + '1'
Meanwhile, once you figure out where and how to call Entrybox, there are a number of problems with it:
def Entrybox():
theinput = inputbox.get()
if type(theinput) is float:
pass
elif type(theinput) is int:
equation += theinput
else:
return 'Numbers Only'
If you've got an inputvar, you really should be using inputvar.get(), not going straight to the Entry. As written, it won't cause any problems, but it makes your code harder to follow.
More seriously, Entry.get always returns a string,* so that theinput can never be an int or a float. So, your comparisons make no sense. And even if they did make sense, that's not the way to check types in Python—use isinstance(theinput, int), not type(theinput). And if you really need to compare types (which is very rare), you should use ==, not is. In general, if you don't know which one you want, you want ==; only use is for specific idiomatic cases (like is None), or when you want to check that two expressions name the exact same object, not just that they have the same value.
Anyway, if you want to check whether the string in inputvar is a string that could be converted to an int, the way to do that is:
try:
value = int(theinput)
equation += theinput
except:
return 'Numbers Only'
And all of the same things apply for float, of course.
Once you fix all of those problems, and any others I didn't spot from a cursory glance, then you can change that return 'Numbers Only' to inputvar.set('Numbers Only'), and you're done.
However, there's a much, much better design for this whole thing. Just make each of the buttons insert a character onto the end of the Entry, and use the Entry's contents (which you can get from inputvar) as the equation, and use either Entry validation or StringVar tracing to handle illegal key entries. There's an example in that blog post, and another example in the official Entry docs linked above.
* Actually, it may be either kind of string—str or unicode—but let's ignore that.

Categories