Initially running the code, blinking will start row wise.
What my software should do is that if the user gives the input "1" in the last row textarea,the blinking should start column wise.
Again if the user give the input "1" then the letter should be selected and should be displayed on the top textarea and entire process should start again
I am not able to control the while loop when the user gives the input in the last row textarea.
I am beginner in python tkinter and I am not able to do what I want exactly.
Thanking You in advance
# your code goes here
import Tkinter
from Tkinter import *
import tkMessageBox
top = Tkinter.Tk()
content=0
def helloCallBack1():
tkMessageBox.showinfo( "Hello Python", "Hello World")
L1 = Label(top, text="Your Text Appears Here")
L1.grid(columnspan=10)
E1 = Entry(top, bd =5,width=40)
E1.grid(columnspan=10)
a1 = Tkinter.Button(top, text ="WATER",width="10", command = helloCallBack1)
a1.grid(row=4,column=0)
B = Tkinter.Button(top, text ="B", command = helloCallBack1)
B.grid(row=4,column=1)
C = Tkinter.Button(top, text ="C",command = helloCallBack1)
C.grid(row=4,column=2)
D = Tkinter.Button(top, text ="D", command = helloCallBack1)
D.grid(row=4,column=3)
E = Tkinter.Button(top, text ="E", command = helloCallBack1)
E.grid(row=4,column=4)
F = Tkinter.Button(top, text ="F", command = helloCallBack1)
F.grid(row=4,column=5)
row1 = Tkinter.Button(top, text =" ", command = helloCallBack1)
row1.grid(row=4,column=6)
a1 = Tkinter.Button(top, text ="ALARM",width="10",bg="red", command = helloCallBack1)
a1.grid(row=5,column=0)
H = Tkinter.Button(top, text ="H", command = helloCallBack1)
H.grid(row=5,column=1)
I = Tkinter.Button(top, text ="I", command = helloCallBack1)
I.grid(row=5,column=2)
J = Tkinter.Button(top, text ="J", command = helloCallBack1)
J.grid(row=5,column=3)
K = Tkinter.Button(top, text ="K", command = helloCallBack1)
K.grid(row=5,column=4)
L = Tkinter.Button(top, text ="L", command = helloCallBack1)
L.grid(row=5,column=5)
row2 = Tkinter.Button(top, text =" ", command = helloCallBack1)
row2.grid(row=5,column=6)
a1 = Tkinter.Button(top, text ="FOOD",width="10", command = helloCallBack1)
a1.grid(row=6,column=0)
N = Tkinter.Button(top, text ="N", command = helloCallBack1)
N.grid(row=6,column=1)
O = Tkinter.Button(top, text ="O",command = helloCallBack1)
O.grid(row=6,column=2)
P = Tkinter.Button(top, text ="P", command = helloCallBack1)
P.grid(row=6,column=3)
Q = Tkinter.Button(top, text ="Q",command = helloCallBack1)
Q.grid(row=6,column=4)
R = Tkinter.Button(top, text ="R", command = helloCallBack1)
R.grid(row=6,column=5)
row3 = Tkinter.Button(top, text =" ", command = helloCallBack1)
row3.grid(row=6,column=6)
a4 = Tkinter.Button(top, text ="BACKSPACE",width="10", command = helloCallBack1)
a4.grid(row=7,column=0)
S = Tkinter.Button(top, text ="S", command = helloCallBack1)
S.grid(row=7,column=1)
T = Tkinter.Button(top, text ="T", command = helloCallBack1)
T.grid(row=7,column=2)
U = Tkinter.Button(top, text ="U", command = helloCallBack1)
U.grid(row=7,column=3)
V = Tkinter.Button(top, text ="V", command = helloCallBack1)
V.grid(row=7,column=4)
W = Tkinter.Button(top, text ="W", command = helloCallBack1)
W.grid(row=7,column=5)
row4 = Tkinter.Button(top, text =" ", command = helloCallBack1)
row4.grid(row=7,column=6)
L2 = Label(top, text="Press 1 when you want to select")
L2.grid(columnspan=10)
E2 = Entry(top, bd =5,width=40)
E2.grid(columnspan=10)
content = E2.get()
content=0;
i=0;j=0;
while(i<30):
row1.after(4000*j+1000*i, lambda: row1.config(fg="red",bg="black"))
row1.after(4000*j+1000*(i+1), lambda: row1.config(fg="grey",bg=top["bg"]))
row2.after(4000*j+1000*(i+1), lambda: row2.config(fg="red",bg="black"))
row2.after(4000*j+1000*(i+2), lambda: row2.config(fg="grey",bg=top["bg"]))
row3.after(4000*j+1000*(i+2), lambda: row3.config(fg="red",bg="black"))
row3.after(4000*j+1000*(i+3), lambda: row3.config(fg="grey",bg=top["bg"]))
row4.after(4000*j+1000*(i+3), lambda: row4.config(fg="red",bg="black"))
row4.after(4000*j+1000*(i+4), lambda: row4.config(fg="grey",bg=top["bg"]))
content=E2.get()
if content==1:#this is not working
break
i=i+1
j=j+1
top.mainloop()
The problem is that your while loop runs in like a blink of an eye, and you cant input anything meanwhile. Because of the after calls the blinking persist, but that does not mean you are still in your wile loop. The program exited that loop long when you input something into the box.
What i would do is to bind the entry box to a key (like Return) and when the key is pressed check the content of the entry box, and if it is 1 then stop the blinking.
Also you can just bind this whole stuff to the 1 key, and avoid the whole Entry widget stuff
Let's think about what you are trying to accomplish: you are trying to cycle through a list of objects, "blinking" one at a time. You want to first do this for objects one row at a time, and later for objects one column at a time.
I am assuming the only thing different between these two behaviors is which items it is iterating over. So, if you create a general purpose function for "blinking" sequentially through a list of objects, you can simply switch which objects are being "blinked".
How would this work? Let's start by creating a list of things to "blink":
blink_objects = [row1, row2, row3, row4]
The idea is that we want to "blink" these, one at a time. To change what is blinking (to switch from rows to columns, as in your question), you simply need to redefine blink_objects.
How would we go about blinking them? The normal way to do this sort of animation is to create a function that draws one frame of the animation, and then schedules itself to run again after a short period of time. In your case that period of time is one second.
Let's call this function blink. We want it to take a couple of optional args, which will be of use later. The first is a variable that contains the object that is currently in a "blink" state. We need this so that we can change it back. The second is a flag that we can use to stop the animation in the future.
Here's what the function looks like. The current_object parameter is passed internally by blink and shouldn't be set when calling blink from somewhere else.
def blink(current_object = None, stop=False):
global blink_objects
# "unblink" the current object
if current_object:
current_object.configure(fg="black", bg=top["bg"])
current_object = None
if not stop:
# blink the first item in the list of objects,
# then move the object to the end of the list
current_object = blink_objects.pop(0)
blink_objects.append(current_object)
current_object.configure(bg="black", fg="red")
# schedule the blink again after a second
current_object.after(1000, blink, current_object)
You only need to call this function once. It will take care of calling itself again every second until the end of time. To get this to blink like your original program, we simply need to replace your whole while loop with these two lines of code:
blink_objects = [row1, row2, row3, row4]
blink()
If at any time you want to stop the animation, you can call blink(stop=True). You might want to do that when the user quits your program, for example.
Next, we need to set it up so that typing "i" changes what is blinking. We can do that by setting a specific binding that will fire immediately when the user presses the key:
E2.bind("<i>", change_blink_objects)
What that says is "if the user presses 'i', call change_blink_objects". Now we just need to define change_blink_objects.
Since this function is called from a binding, it will be passed an object that represents the event (what key was pressed, what object got the keypress, etc). At the moment we don't need that information, but we have to accept it.
Within the function, I'm guessing you'll it to intelligently pick the objects to blink, but I don't know what that logic is, so I'll just have it blink the "alarm" row.
def change_blink_objects(event):
global blink_objects
blink_objects = [H, I, J, K,. L)
That's all you have to do: create a generic function for blinking a list of objects, and a binding that calls a function that changes the list of objects.
Make sure when you're testing this that you first click in the entry widget or it won't see when you type "i".
While loops and GUIs do not mix very well. Youe while loop creates 240 delayed callbacks that you cannot cancel. Instead, you should have one delayed callback that conditionally creates another. Here is an untested replacement for your loop. It incorporates Gabor's answer and should get you started,
go = True
def stop():
go = False
root.bind('<key-1>', stop)
def blink(i, j):
if i = 0:
row1.config(fg="red",bg="black"))
if j > 0:
row4.config(fg="grey",bg=top["bg"]))
elif i = 1:
row1.config(fg="grey",bg=top["bg"]))
row2.config(fg="red",bg="black"))
elif i = 2:
row2.config(fg="grey",bg=top["bg"]))
row3.config(fg="red",bg="black"))
elif i = 3:
row3.config(fg="grey",bg=top["bg"]))
row4.config(fg="red",bg="black"))
if go and j < 30:
top.after(1000, blink, (i+1) % 4, j+1)
top.after(1000, blink, 0, 0)
Related
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)
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()
'''
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.
I am new to Python and I am writing a program just for fun. My program consists of three .py files (let's say a.py, b.py, c.py). a will either call on the functions within either b or c, depending on the user's option. After it completes its first round it asks if the user would like to continue or simply exit the program. If they chose continue it asks again whether it should run b or c.
The problem I ran into is that the first time around, a will call the functions in either perfectly fine, it runs smoothly, and then when I select to continue it again calls either function perfectly fine, it will go into the function, but then the function gets stuck in its first step.
The program is not terminating, not giving an error. It accepts the raw_input variable but it will not continue. I was wondering if there was some way to force it to accept the variable and then continue the process (getting it 'unstuck'). I already tried putting pass on the next line. That didn't work.
Here are the steps it takes starting from the request to continue:
Continue = tkMessageBox.askyesno('Cypher Program', 'I have completed the task'
+ '\nWould you like to do anything else?')
## This is in a.py;
if Continue == True:
cyp()
def cyp():
global root
root = Tk()
root.title("Cypher Program")
root['padx'] = 40
root['pady'] = 20
textFrame = Frame(root)
Label(root, text = 'What would you like to do?').pack(side = TOP)
widget1 = Button(root, text = 'Encrypt a file', command = encrypt)
widget1.pack(side = LEFT)
widget2 = Button(root, text = 'Decrypt a file', command = decrypt)
widget2.pack(side = RIGHT)
widget3 = Button(root, text = 'Quit', command = quitr)
widget3.pack(side = BOTTOM)
root.mainloop()
def encrypt():
root.destroy()
encrypt3.crypt()
##Then from there it goes to b.py;
def crypt():
entry('Enter a file to encrypt:', selectFile)
def entry(msg1, cmd):
global top
top = Toplevel() ##changed it to Toplevel
top.title("File Encrypion")
top['padx'] = 40
top['pady'] = 20
textFrame = Frame(top)
entryLabel = Label(textFrame)
entryLabel['text'] = msg1
entryLabel.pack(side = LEFT)
global entryWidget
entryWidget = Entry(textFrame)
entryWidget['width'] = 50
entryWidget.pack(side = LEFT)
textFrame.pack()
button = Button(top, text = "Submit", command = cmd)
button.pack()
button.bind('<Return>', cmd)
top.mainloop()
def selectFile():
if entryWidget.get().strip() == "":
tkMessageBox.showerror("File Encryption", "Enter a file!!")
else:
global enc
enc = entryWidget.get().strip() + '.txt'
top.destroy() ##gets stuck here
##This is the rest of crypt(). It never returns to the try statement
try:
view = open(enc)
except:
import sys
sys.exit(badfile())
text = ''
You need to restructure your code to only create the root window once, and only call mainloop once. Tkinter is not designed to be able to create and destroy the root multiple times in a single process.
If you need multiple windows, create additional windows with the Toplevel command.