So i've made a project for school, and it won't run and i have no idea why. Everytime i press the "start" button i made, the whole program freezes and stops working, and seeing as i've made a similar program earlier(this one is just much cleaner) i get really confused.
here is the code:
from tkinter import *
root=Tk()
root.minsize(width=3, height=100)
root.title("Counter")
list=[]
list.append(0)
def counter():
t = 10
c = 0
for row in list:
if (t < 60) or (c < 5):
l=Label(root, text=t).grid(row=1, column=c)
t=10+10
c=0+1
list.append(t)
print("") #This is just for debugging purpose
for row in list:
if (t < 110) or (c < 10):
c=0
ll=Label(root, text=t).grid(row=2, column=c)
c=0+1
t+10
list.append(t)
return
label=Label(root, text="...").grid(row=0, column=0)
b=Button(root, text="Start", command=counter).grid(row=0, column=1)
label=Label(root, text="...").grid(row=0, column=2)
root.mainloop()
Thanks for all the tips, figured it out due to you! :D
The problem is that you're modifying the list you're iterating over. Besides list isn't a good name as it shadows the builtin one, you always append an element to your list.
Additionally, none of the conditions will be met since t is always assigned to 20 and c to 1.
The reason it is freezing is because you are modifying list while looping over it:
list.append(t)
You did that twice. You can not do it in this manner and you should either use a separate list to carry out whatever you were trying to do or some sort of list iterator. Also as already noted,
t+10
has no affect and you should not be naming your list "list" anyways since it is a reserved word for a different purpose.
Related
I couldn't word my question well but here's some context.
I created a button in tkinter and I used .place(x, y) inside an if condition but now I want to destroy it if another condition is met. It doesn't get destroyed even if the second condition is met. Please help.
from tkinter import *
window = Tk()
button = Button(window, text='Button')
x = 10
y = 10 # just imagine that y became 5 at some point
if x == 10:
button.place(x=0, y=0)
elif y == 5:
button.destroy()
window.mainloop()
I am not exactly sure what you want to accomplish here, but you seem to be misunderstanding how if-elif-else works. It is intended to give alternatives for the values of the same variable, or in any case, both possibilities shouldn't be possible to happen simultaneously to get the desired outcome. Elif is short for "else if", meaning that it's evaluated only if the "if" statement is false.
In your case, x is already equal to 10 and you aren't changing it at any point, so the "if" condition is always fulfilled and the code never gets to the "elif" statement.
If y is changing and reaches 5, you could change the "elif" statement into "if" and add the condition that y has to be not equal to 5 when creating the button (otherwise, it will constantly create and destroy itself).
Also, as your current code works, there is no loop running. The code evaluates only once.
If I understand what you want to do, it's something along these lines.
from tkinter import *
window = Tk()
x = IntVar()
y = IntVar()
x.set(10)
y.set(10)
button = Button(window, text='Button', command=lambda: y.set(5))
def loop_this():
if (x.get() == 10) and (y.get() != 5):
button.place(x=0, y=0)
if y.get() == 5:
button.destroy()
window.after(1000, loop_this)
loop_this()
window.mainloop()
In general, it's good to use Tkinter variables (IntVar, StringVar, BoolVar) when working with Tkinter. To replicate a scenario where y = 5, I made it be equal to 5 when the button is pressed, but it can be changed elsewhere in the code and it will work in the same way.
The main thing is to put the thing into a function, attach it to the main window and run it in a loop. To do that we use .after(time_in_miliseconds_between_loops, function_to_loop_without_brackets)
and call the function before window.mainloop().
Hopefully this answers your question.
I am creating a search function in my tkinter program and I have a problem with empty widgets getting packed if the ifstatement where the widgets should get packed in is false.
I try to explain what I am trying to do:
I have a while loop which is looping through all files in a folder.
In the while loop is a if statement which checks if the filename contains the searched letters.
If yes, a Label with the filename will be packed. If no, nothing should happen.
But when the filename doesn´t contain the searched letters, a empty widget is been packed.
Here is a short example of my code:
whileLoop = True
search = Entry(root)
fileNameList = ["abc","def","ghi"]
whileLoopCounter = 0
while whileLoop == True:
if search in fileNameList[whileLoopCounter]:
Label(root, text=fileNameList[whileLoopCounter])
whileLoop = False
whileLoopCounter += 1
This is a very short version of my code, because the real code would be way to long. But I hope you understand what I am trying to do.
Thanks for your help.
search = Entry(root)
fileNameList = ["abc","def","ghi"]
for d in fileNameList:
if d in search.get():
Label(root, text=d)
try this! it uses "any". Also you need to do "in" on 'each' string not
on the whole list!
I know this question has been asked a few times, but not one of the other solutions has applied to my problem.
I have a variable list of "anomalies" stored as a tuple holding the anomaly name and either a 0 or 1, determining whether or not to notify the user of something. Because the list is of variable length, the checkbuttons need to be created in a for loop.
I want to create a popup that shows a list of checkbuttons, to allow the user to edit the notification values to their preference. However, the implementation of this idea that I've used causes the checkbuttons to not change the value of their variables or display the proper on/off state.
Here's my code:
notif_anoms = [("Anomaly 1", 1), ("Anomaly 2", 0)]
checkbox_vars = []
def select_desired_anomaly_checks(self):
popup = Tk()
popup.wm_title("Desired Anomalies")
len_a = len(self.notif_anoms)
for i in range(0, len_a):
msg, on = self.notif_anoms[i]
self.checkbox_vars.append(IntVar(value=on))
self.checkbox_vars[-1].set(on)
tk.Checkbutton(popup, text=msg, variable=self.checkbox_vars[-1], onvalue=1, offvalue=0, command=self.update_vars).grid(row=i, sticky=W)
popup.resizable(0, 0)
popup.mainloop()
def update_vars(self):
for i in range(0, len(self.checkbox_vars)):
var = self.checkbox_vars[i]
print(var.get())
self.notif_anoms[i] = (self.notif_anoms[i][0], var.get())
print('------------------')
The only problem I can think of with this is that I'm setting the IntVar inside of the for loop, but as far as I can think of, there's no other way to create a list of checkboxes at runtime with unknown length.
Any and all help is appreciated, thank you.
I am creating a simple tkinter list and populating it with a list of numbers. then I am deleting a part of the list and want that change to reflect in the listbox as soon as I run the delete function.
I used the update_idletasks() in the function but it does not update the list. Can some one assist me to resolve this issue?
from tkinter import *
main = Tk()
b1 = Button(main,text='delete section',command=lambda:func())
b1.pack()
l1 = Listbox(main)
l1.pack()
mylist =[]
for i in range(0,100):
mylist.append(i)
for k in mylist:
l1.insert(0,k)
def func():
del mylist[50:100]
l1.update_idletasks()
main.mainloop()
update_idletasks(self)
Enter event loop until all idle callbacks have been called. This will update the display of windows but not process events caused by the user.
update_idletasks is not what you're wanting to use if you just want to update the Listbox with the new list.
There are a few ways you can do this. You can delete all items from index 50 to 100
l1.delete(50, 100)
Or you can delete every item from the list and add them again
del mylist[50:100]
li.delete(0, END)
for k in mylist:
l1.insert(0, k)
Also, if you wish to use the first option, deleting from index 50 to 100. You'll need to change your current insert line from l1.insert(0, k) to l1.insert(END, k) this way it adds to the list in a ascending order.
I'm mentioning this because it appears you want to keep 0, 1, .. , 48, 49. But if you want them in descending order then use l1.delete(0, 49) instead.
I have trouble finding a way to limit the entry length of entry widgets, I would like to limit it to 20 characters, i.e. when I click on a sequence or the other I would like to be able to edit it but stay in the 20 characters limit. In or order to keep the code light , should I use a regex , a loop or check the entry with an event ?
Here is my code:
import Tkinter
from Tkinter import *
import tkFileDialog
root = Tkinter.Tk()
edit1 =StringVar()
edit2 =StringVar()
s = StringVar()
s = "GATACACGCGCGCGTATATATTACGCGCGCGATACA"
lb01=Label(root,text="sequence1")
lb01v=Entry(root,textvariable=edit1,width=20)
lb01v.delete(0, END)
lb01v.insert(0, s[6:20])
lb01.grid(sticky=W,row=1,column=1)
lb01v.grid(row=1,column=2)
lb02=Label(root,text="sequence2")
lb02v=Entry(root,textvariable=edit2,width=20)
lb02v.delete(0, END)
lb02v.insert(0, s[0:6])
lb02.grid(sticky=W,row=2,column=1)
lb02v.grid(row=2,column=2)
root.mainloop()
Ok I did try with the trace variable, on a short piece of test code , this is excactly what I was searching for !! I like the fact you can prototype so easily in Python ;)
def main():
pass
if __name__ == '__main__':
main()
from Tkinter import *
def callback(sv):
c = sv.get()[0:9]
print "c=" , c
sv.set(c)
root = Tk()
sv = StringVar()
sv.trace("w", lambda name, index, mode, sv=sv: callback(sv))
e = Entry(root, textvariable=sv)
e.pack()
root.mainloop()
I know its too late to add any answers to this, just found a simpler way to represent what Wabara had answered. This will help if you need multiple entry limits and each to a user-defined length limit. Here's a code working on Python 3.6.5:
def main():
pass
if __name__ == '__main__':
main()
from tkinter import *
def limit_entry(str_var,length):
def callback(str_var):
c = str_var.get()[0:length]
str_var.set(c)
str_var.trace("w", lambda name, index, mode, str_var=str_var: callback(str_var))
root = Tk()
abc = StringVar()
xyz = StringVar()
limit_entry(abc,3)
limit_entry(xyz,5)
e1 = Entry(root, textvariable=abc)
e2 = Entry(root, textvariable=xyz)
e1.pack()
e2.pack()
root.mainloop()
The simplest solution is to put a trace on the variable. When the trace fires, check the length of the value and then delete any characters that exceed the limit.
If you don't like that solution, Tkinter also has built-in facilities to do input validation on entry widgets. This is a somewhat under-documented feature of Tkinter. For an example, see my answer to the question Python/Tkinter: Interactively validating Entry widget content
I will start off by making an alphabet to measure from. The alphabet is a string and has 26 letters meaning its too long for our use. we want 20 letters only, so our output should be "A" thru "T" only.
I would define a function to make it happen and dump each string thru it that I would want cut to 20 characters or less.
I am making the below code in such a way that it takes as an input any string that is called it takes that input in and processes it to 20 characters in length only...
def twenty(z):
a = z[0:20]
return a
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
so to execute our newly made code, we need only call the print twenty command with the variable we want cut to 20 characters in the parenthesis.
print twenty(alphabet)
-----------------------------------------------------------------
OUTPUT:
ABCDEFGHIJKLMNOPQRST
So you see, it worked, we input the entire alphabet into the program and it cut the string down to 20 letters only. now every time in your code you want to cut text down to 20 letters, just run the command
twenty(variable)
and it will make sure you have no more letters than that.
Explanation:
def twenty is to define a function with one input that you can call on over and over simply by typing twenty(variable)
the next line is a = z[0:20] Meaning call variable "a" to equal the input from position 0 to position 20 and dont worry about anything past that.
return command is how you get an output from the def function. anytime you create a def function, you should end it with a line.