Why is last button/task removed in this code? - python

I have a block of code which is called on a button press. The aim is to remove the task the button represents, and update all the other buttons to reflect the time changes. The function take an argument pos which is the position in the list of tasks to remove. That task entry is removed and the remaining task times updated.
The buttons are all removed and re-placed with new times and positions etc.
def remove_task(self, pos, *args):
print("\nRemoving task...")
print("List size = " + str(len(self.scheduled_tasks)))
print("Task pos = " + str(pos))
print("Task name = " + str(self.scheduled_tasks[pos].name))
del self.scheduled_tasks[pos] #Task deleted from list
print("Task deleted!")
print("Tasks:")
for task in self.scheduled_tasks:
print(task.name)
print("Re-assigning task n values...")
for index, tasks in enumerate(self.scheduled_tasks):
print("Index = " + str(index))
self.scheduled_tasks[index].n = int(index)
print("Name: " + str(self.scheduled_tasks[index].name))
print("N = " + str(self.scheduled_tasks[index].n))
print("N assingments complete")
print("List size = " + str(len(self.scheduled_tasks)))
for i in self.scheduled_tasks:
print("Task " + str(i.n) + " = " + str(i.name))
print("Deleting buttons...")
print("Number of buttons = " + str(len(self.ids.schedule.children)))
self.ids.schedule.clear_widgets()
print("Buttons deleted!")
position = 0
for i in self.scheduled_tasks:
print("Creating new buttons...")
if i.n == 0:
print("First button")
print("I.n = "+ str(i.n))
task_name = self.scheduled_tasks[i.n].name
print("Name = " + task_name)
task_time = self.scheduled_tasks[i.n].size
print("Task time = " + str(task_time))
parent_size = self.day
initial = App.get_running_app().user_start_time
end = initial + task_time
print("Task end time = " + str(end))
self.scheduled_tasks[i.n].set_start_time(initial)
self.scheduled_tasks[i.n].set_end_time(end)
print("New times set!")
if self.scheduled_tasks[i.n].class_type == "task":
print("Finding task size...")
self.task_size = self.scheduled_tasks[i.n].decimal_size
print("Size = " + str(self.task_size))
button_size = 1/int(parent_size/self.task_size)
print("Button_size = " + str(button_size))
task_type = self.scheduled_tasks[i.n].type
self.rgba = set_task_color(task_type, self.task_name).split(",")
if self.scheduled_tasks[i.n].class_type == "break":
button_size = 1/(self.parent_size/(self.break_size_init/60))
self.rgba = [0.5,0.5,0.5,0.5]
print("Position = " + str(position))
self.scheduled_tasks[i.n].n = position
position = position + 1
print("Position in scheduled tasks = " + str(self.scheduled_tasks[i.n].n))
task_button = Button(text = task_name + "\n" + str(self.scheduled_tasks[i.n].start_time.strftime("%H:%M")) + "\n - \n" + str(self.scheduled_tasks[i.n].end_time.strftime("%H:%M")),
size_hint = (button_size, 0.5),
text_size = (None, None),
font_size = 12,
pos_hint = {"top": 1},
background_normal = "white",
background_color = self.rgba)
task_button.text_size = task_button.size
task_button.halign = "center"
task_button.n = self.scheduled_tasks[i.n].n
print("Button position = " + str(task_button.n))
task_button.bind(on_release = lambda x: self.ids.schedule.remove_widget(task_button))
if self.scheduled_tasks[i.n].class_type == "task":
task_button.bind(on_release = lambda x: self.remove_task(i.n))
elif self.scheduled_tasks[i.n].class_type == "break":
task_button.bind(on_release = lambda x: self.remove_break(i.n))
print("Button functions bound")
self.ids.schedule.add_widget(task_button)
else:
print("Subsequent button")
print("I = " + str(i.n))
task_name = self.scheduled_tasks[i.n].name
print("Name = " + task_name)
print("Calculating times...")
initial = self.scheduled_tasks[i.n-1].end_time
end = initial + self.scheduled_tasks[i.n].size
print("Assigning times...")
self.scheduled_tasks[i.n].set_start_time(initial)
self.scheduled_tasks[i.n].set_end_time(end)
print("New times set!")
if self.scheduled_tasks[i.n].class_type == "task":
c.execute("SELECT Size FROM Tasks WHERE Name = ?;", (self.task_name,))
task_size_raw = "".join(c for c in str(str(c.fetchall())) if c not in "[](''`),")
self.task_size = float(task_size_raw) #hours, decimal
button_size = 1/int(parent_size/self.task_size)
task_type = self.scheduled_tasks[i.n].type
self.rgba = set_task_color(task_type, self.task_name).split(",")
if self.scheduled_tasks[i.n].class_type == "break":
button_size = 1/(self.parent_size/(self.break_size_init/60))
self.rgba = [0.5,0.5,0.5,0.5]
position = position + 1
print("position = " + str(self.scheduled_tasks[i.n].n))
task_button = Button(text = task_name + "\n" + str(self.scheduled_tasks[i.n].start_time.strftime("%H:%M")) + "\n - \n" + str(self.scheduled_tasks[i.n].end_time.strftime("%H:%M")),
size_hint = (button_size, 0.5),
text_size = (None, None),
font_size = 12,
pos_hint = {"top": 1},
background_normal = "white",
background_color = self.rgba)
task_button.text_size = task_button.size
task_button.halign = "center"
task_button.n = i.n
print("Button position = " + str(task_button.n))
task_button.bind(on_release = lambda x: self.ids.schedule.remove_widget(task_button))
if self.scheduled_tasks[i.n].class_type == "task":
task_button.bind(on_release = lambda x: self.remove_task(i.n))
elif self.scheduled_tasks[i.n].class_type == "break":
task_button.bind(on_release = lambda x: self.remove_break(i.n))
print("Button functions bound")
self.ids.schedule.add_widget(task_button)
print("Done!" + "\n")
print("Buttons created!")
print("Re-ordering complete!" + "\n")
Removing a task in the first instance works but when removing any later tasks/buttons the last task is always removed. The code output shows the button function is correctly bound to call the correct position argument but then always removes the last button/last entry in the list of tasks.
Output:
Removing task...
List size = 3
Task pos = 1 #Correct position
Task name = Test2
Task deleted!
Tasks:
Test
Test3
Re-assigning task n values...
Index = 0
Name: Test
N = 0
Index = 1
Name: Test3
N = 1
N assingments complete
List size = 2
Task 0 = Test
Task 1 = Test3
Deleting buttons...
Number of buttons = 3
Buttons deleted!
Creating new buttons...
First button
I.n = 0
Name = Test
Task time = 2:00:00
Task end time = 2021-01-03 16:30:00
New times set!
Finding task size...
Size = 2.0
Button_size = 0.5
0.8943980039499027,0.2144472118229821,0.011421795014607938,0.7
Position = 0
Position in scheduled tasks = 0
Button position = 0
Button functions bound
Creating new buttons...
Subsequent button
I = 1
Name = Test3
Calculating times...
Assigning times...
New times set!
0.8943980039499027,0.2144472118229821,0.011421795014607938,0.7
position = 1
Button position = 1
Button functions bound
Done!
Buttons created!
Re-ordering complete!
#^First removal, works fine with no issues^
Removing task...
List size = 2
Task pos = 1 #I clicked the button for the first task (Task 0) and this position argument was given!
Task name = Test3
Task deleted!
Tasks:
Test
Re-assigning task n values...
Index = 0
Name: Test
N = 0
N assingments complete
List size = 1
Task 0 = Test
Deleting buttons...
Number of buttons = 2
Buttons deleted!
Creating new buttons...
First button
I.n = 0
Name = Test
Task time = 2:00:00
Task end time = 2021-01-03 16:30:00
New times set!
Finding task size...
Size = 2.0
Button_size = 0.5
0.8943980039499027,0.2144472118229821,0.011421795014607938,0.7
Position = 0
Position in scheduled tasks = 0
Button position = 0
Button functions bound
Buttons created!
Re-ordering complete!
Removing task...
List size = 1
Task pos = 0
Task name = Test
Task deleted!
Tasks:
Re-assigning task n values...
N assingments complete
List size = 0
Deleting buttons...
Number of buttons = 1
Buttons deleted!
Buttons created!
Re-ordering complete!
#^Second and all subsequent removals remove the last task^
Can anybody see why the button is calling the last task instance to be removed? Why does every button after one task is correctly removed call for the last task to be removed?
I appreciate this is a long and detailed question so thanks in advance for any of your time!

I fixed this by binding a partial function instead of lambda to call the function on the button press. So instead of lambda x: remove_task(i.n) it would be partial(remove_task,i.n)

Related

Tkinter freeze and won't load the result on screen

I'm new to programming and I'm trying to make an app that calculates the smallest common for you, but for some reason whenever i run it, tkinter seems to just freeze and i don't know what the error seems to be. I suspect that it's the myLabel part, since I can still read the result inside the Terminal.
Thanks in advance~
from tkinter import *
root = Tk()
root.title("I can find the smallest common, unless you enter letters... I'm dyslexic.")
numbers_list = []
global numbers
numbers = Entry(root, width = 10, borderwidth = 5, state = DISABLED)
numbers.pack()
numbers.insert(0, "")
#
def button_click():
#each gets a button
get_smallest_common = Button(root, text = 'Confirm your number!'
, command = smallest_common)
get_smallest_common.pack()
get_smallest_common = Button(root, text = 'Undo!'
, command = lambda: undo())
get_smallest_common.pack()
get_smallest_common = Button(root, text = 'Start the search!'
, command = lambda: find_the_s_common())
get_smallest_common.pack()
#disable the start button
def switch():
myButton['state'] = DISABLED
#configure helps bringing a disabled thing back to normal state
numbers.configure(state = "normal")
def smallest_common():
#add to the list for late use
numbers_list.append(numbers.get())
print(numbers_list)
numbers.delete(0, END)
def undo():
#add to the list for late use
numbers_list.pop()
print(numbers_list)
numbers.delete(0, END)
def find_the_s_common():
process_list = []
condition = True
x = 0
while condition:
#the multiplication keep rising till count is 3
a = int(x) + 1
x = a
#loop to multiply the number with x + 1
for number in numbers_list:
y = int(number) * int(a)
process_list.append(y)
#check whether the result has been added to append into list
if y in process_list:
#check whether the list contains two duplicates to
if process_list.count(y) == 3:
condition = False
result = 'The number is ' + str(y) + '!'
print(result)
else:
continue
else:
continue
myLabel = Label(root, text = result)
myLabel.pack()
#combine the two function for myButton
def button_click_switch():
button_click()
switch()
myButton = Button(root, text = 'Click me to start'
, command = lambda: [button_click(), switch()])
myButton.pack()
root.mainloop()
Most probably, you have problem if the numbers entered is less than 3. As a result, one simple way is to decrease the condition to 2 and if a single number is entered the result is the number itself, if 2 or more no freezing.
NOTE: Freezing here is actually, while loop is running as condition is always True, because of process_list.count(y) == 3 will always be False if less than 3 number entered.
See my suggestion:
from tkinter import *
root = Tk()
root.title("I can find the smallest common, unless you enter letters... I'm dyslexic.")
numbers_list = []
global numbers
numbers = Entry(root, width = 10, borderwidth = 5, state = DISABLED)
numbers.pack()
numbers.insert(0, "")
#
def button_click():
#each gets a button
get_smallest_common = Button(root, text = 'Confirm your number!', command = smallest_common)
get_smallest_common.pack()
get_smallest_common = Button(root, text = 'Undo!', command = lambda: undo())
get_smallest_common.pack()
get_smallest_common = Button(root, text = 'Start the search!' , command = lambda: find_the_s_common())
get_smallest_common.pack()
#disable the start button
def switch():
myButton['state'] = DISABLED
#configure helps bringing a disabled thing back to normal state
numbers.configure(state = "normal")
def smallest_common():
#add to the list for late use
numbers_list.append(numbers.get())
print(numbers_list)
numbers.delete(0, END)
def undo():
#add to the list for late use
numbers_list.pop()
print(numbers_list)
numbers.delete(0, END)
def find_the_s_common():
process_list = []
condition = True
x = 0
if len(numbers_list) == 1: # RETURN IF THE LIST HAS A SINGLE VALUE
result = 'The number is ' + str(numbers_list[0]) + '!'
else:
while condition:
#the multiplication keep rising till count is 3
a = int(x) + 1
x = a
#loop to multiply the number with x + 1
for number in numbers_list:
y = int(number) * int(a)
process_list.append(y)
#check whether the result has been added to append into list
if y in process_list:
#check whether the list contains two duplicates to
if process_list.count(y) == 2: # DECREASE THE CONDITIONS TO 2
condition = False
result = 'The number is ' + str(y) + '!'
print(result)
else:
continue
else:
continue
myLabel = Label(root, text = result)
myLabel.pack()
#combine the two function for myButton
def button_click_switch():
button_click()
switch()
myButton = Button(root, text = 'Click me to start', command = lambda: [button_click(), switch()])
myButton.pack()
root.mainloop()
Suggestion to add two conditons;
(1) create a condition until at least 1 number is entered! if len(numbers_list) == 0, loop to enter a number.
(2) create a condition, until N number is added, let's say user must enter at least 3 numbers, change process_list.count(y) == 3 to process_list.count(y) == N and add condition if len(numbers_list) != N, loop to enter more numbers.

python class attribute not updating when updated in a function

I have a stopwatch of sorts going in the background using threading, and while it's updating the global variable, it doesn't change the output of my class attribute.
This is what I have:
import time
from threading import Thread
s = 0
m = 0
h = 0
stopped = False
def stopwatch():
global s
global m
global h
global stopped
while stopped == False:
s = s + 1
if s >= 60:
s = 0
m += 1
if m >= 60:
m = 0
h += 1
time.sleep(1)
class foo:
name = 'shirb'
time = str(h) + 'h' + str(m) + 'm' + str(s) +'s'
Thread(target = stopwatch).start()
input('press enter to stop the stopwatch')
stopped = True
print('Name: ' + foo.name + '\nTime: ' + foo.time)
Lets say I wait for one minute and 34 seconds.
The output should be:
press enter to stop the stopwatch
Name: shirb
Time: 0h1m34s
But this is what it actually puts out:
press enter to stop the stopwatch
Name: shirb
Time: 0h0m0s
I have no idea what is causing it to not update. When I try to print the variable itself with "print(s)" i get the correct amount of seconds, so there is something wrong with the class attribute that I don't know how to fix.
Class variables are initialized at module load time, so foo.time is set when h, m, and s, are zero. If you make it a class method, however, you will get the right result:
class foo:
name = 'shirb'
#classmethod
def cls_time(cls):
return str(h) + 'h' + str(m) + 'm' + str(s) +'s'
Thread(target = stopwatch).start()
input('press enter to stop the stopwatch')
stopped = True
print('Name: ' + foo.name + '\nTime: ' + foo.cls_time())
You could perhaps use just the one class:
import time
from threading import Thread
class stopwatch:
def __init__(self):
self.s = 0
self.m = 0
self.h = 0
self.stopped = False
self.name = "shirb"
def begin(self):
while self.stopped is False:
self.s += 1
if self.s >= 60:
self.s = 0
self.m += 1
if self.m >= 60:
self.m = 0
self.h += 1
time.sleep(1)
def get_time(self):
return str(self.h) + "h" + str(self.m) + "m" + str(self.s) + "s"
s = stopwatch()
Thread(target=s.begin).start()
input("press enter to stop the stopwatch")
s.stopped = True
print("Name: " + s.name + "\nTime: " + s.get_time())
This solves the issue.

Python tkinter can't use Entry.get() fucntion

So I have been working on a quizzing application for some time now (about 4 days). I managed to make all the logical part of the code (the quiz taking, the quiz question handling, score outputting, etc.) I know that this code is neither the best nor the most efficient as it can be but I'm just a beginner. Anyways, the get() function for the entry function for tkinter does not return anything. I am aware that there is a way to fix it however I'm not sure how to implement the solution with an external loop. Please help me. Here is my code:
import random
from time import sleep
import tkinter as tk
from tkinter import *
import threading
class App(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.start()
def callback(self):
self.root.quit()
def run(self):
self.root = tk.Tk()
self.root.protocol("WM_DELETE_WINDOW", self.callback)
#label = tk.Label(self.root, text="Hello World")
#label.pack()
#Button(self.root, text = "Choose", command=btnPressed).pack()
tk.Label(self.root, text="Answer: ").grid(row=0,column=0)
#answerField_get = StringVar()
answerField = tk.Entry(self.root)
answerField.grid(row=0, column=1)
#Button(self.root, text='Show').grid(row=3, column=1, sticky=tk.W, pady=4)
print(str(answerField.get()))
Button(self.root, text='Show', command = lambda arg1=answerField.get():btnPressed("<"+str(arg1)+">")).grid(row=3, column=1, sticky=tk.W, pady=4)
self.root.mainloop()
def sendTMP(self, sendStr):
btnPressed(sendStr)
SCORE_SET = []
qasTmp = {}
qas = {}
qasSequenced = {}
incorrectResponses = []
incorrectResponses_replies = []
quiztaker_name = ""
attachAnsCode = "%% Fun fact: rgb computer parts lovers are somewhat weird hehe %%********^^&&^^&&^^&&"
qasQsSequenced = False
qasQsL = 0
qasQsL_divisionFactor = 2
qasINDEX = 0
err_noCode = "<!>NO_CODE<!>"
codes_answerCorrect = "A_C"
codes_answerIncorrect = "A_I"
answerCode = err_noCode
score = 0
randQs = False
# File
# the metadata will corrupt the reading from the file, a separate file, created in the targeted system, must be used to properly read the data.
# comment out the file name that is not being used.
filename_windows = "qas-windows"
filename_rpi = "qas-rpi"
filename = filename_windows
fileformat = "txt"
file_name_format = filename + "." + fileformat
spaceIndicator = "|"
char_commentLine_qasFile = "*"
char_newline = "`"
print("Information about modes: ")
print(" *Easy: No point deductions for an incorrect response")
print(" *Hard: One point deducted for every incorrect response")
modes_err = "0"
modes_ez = "1"
modes_hard = "2"
gameOn = False
selectedMode = modes_err
askReplay = True
data_prev = []
with open("SCORES.txt", 'r') as scores_prev:
data_prev = scores_prev.readlines()
scores_prev.close()
for i in range(0, len(data_prev)):
SCORE_SET.append(data_prev[i])
def btnPressInform():
print("A button has been pressed!")
def importAndClean():
# import questions from qas-windows.txt
with open(file_name_format, 'r') as document:
for line in document:
if line.strip():
key, value = line.split(None, 1)
if key[0] != char_commentLine_qasFile: # Custom comments for the txt file
qasTmp[key] = value.split()
# Clean up dictionary input from the txt file
for i in range(0, len(qasTmp)): # FIVE FOR LOOPS!!!! (FOUR IN THIS ONE)
for ii in qasTmp:
output = ""
output_ans = ""
for iii in range(0, len(ii)):
if ii[iii] != spaceIndicator:
output += ii[iii]
else:
output += " "
for iiii in range(0, len(qasTmp[ii])):
TEMP = str(qasTmp[ii])
for iiiii in range(2, len(TEMP) - 2): # IGNORE [' and ']
# print(TEMP[iiiii])
if TEMP[iiiii] != spaceIndicator:
output_ans += TEMP[iiiii]
else:
output_ans += " "
# print(output + " : " + output_ans) #Output question: answer
qas[output] = output_ans
importAndClean()
def getL():
qasQsL = len(qas) / qasQsL_divisionFactor # only ask 1/qasQsL_divisionFactor the questions
qasQsL = int(qasQsL) # round to an integer as odd numbers will end in .5 after division
if qasQsL < 1:
qasQsL = 1 # Have atleast ONE question
return qasQsL
def debug1(keys, vals, index, i):
print(str(index) + "/" + str((len(keys) - 1)))
print(keys)
print(vals)
print()
print(keys[index] + " : " + vals[index] + "\n")
print("Sorting original index " + str(i) + " at random index " + str(index))
def debug2(keys, vals, index):
print(keys)
print(vals)
print("\n")
def debugFinal():
print("Temp (OG reading): ")
print(qasTmp)
print("\nQAS (Non-sequenced, cleaned): ")
print(qas)
print("\nQAS Sequenced (Randomly sequenced, cleaned): ")
print(qasSequenced)
def randomize(qasQsL_tmp):
qas_keys = list(qas.keys())
qas_vals = list(qas.values())
if randQs == False:
qasQsL_tmp = len(qas_keys) # all questions
print("You will be asked all " + str(qasQsL_tmp) + " questions")
else:
qasQsL_tmp = getL() # random question
print("You will be asked " + str(qasQsL_tmp) + " questions out of " + str(len(qas)) + " possible questions!")
print("\n\nRandomly sequencing questions...")
for i in range(0, qasQsL_tmp):
INDEX = random.randint(0, qasQsL_tmp - 1)
# debug1(qas_keys, qas_vals, INDEX, i)
qasSequenced[qas_keys[INDEX]] = qas_vals[INDEX]
qas_keys.pop(INDEX)
qas_vals.pop(INDEX)
qasQsL_tmp -= 1
# debug2(qas_keys, qas_vals, INDEX)
sleep(0.05)
# debugFinal()
print("Done sequencing! Starting quiz now! \n\n")
return "0"
def quizController(index):
qas_keys = list(qasSequenced.keys())
qas_vals = list(qasSequenced.values())
# print(qas_keys)
# print(qas_vals)
lines = []
lines_index = 0
tmp = ""
# Splitter
for i in range(0, len(qas_keys[index])):
if lines_index < len(qas_keys[index]) - 1:
if qas_keys[index][i] != char_newline:
tmp += qas_keys[index][i]
else:
lines.append(tmp)
tmp = ""
lines.append(tmp)
# Multiple choice
mChoiceQ = False
mChoice_startBrackets = 0
mChoice_endBrackets = 0
mChoice_options = []
mChoice_numOptions = 0
mChoice_seperatorsAt = []
for i in range(0, len(qas_keys[index])):
if qas_keys[index][i] == "[":
mChoice_startBrackets = i
mChoiceQ = True
elif qas_keys[index][i] == "]":
mChoice_endBrackets = i
elif qas_keys[index][i] == "/":
mChoice_seperatorsAt.append(i)
if mChoiceQ == True:
TEMP = ""
for i in range(mChoice_startBrackets, mChoice_endBrackets + 1):
if qas_keys[index][i] != "[":
if qas_keys[index][i] != "/" and qas_keys[index][i] != "]":
TEMP += qas_keys[index][i]
else:
mChoice_options.append(TEMP)
TEMP = ""
mChoice_numOptions = len(mChoice_seperatorsAt) + 1
# Default options (yes, no) full names
for i in range(0, len(mChoice_options)):
if mChoice_options[i].lower() == "y":
mChoice_options.append("yes")
elif mChoice_options[i].lower() == "n":
mChoice_options.append("no")
# if mChoiceQ == True:
# print("It is a multiple choice question! There are " + str(mChoice_numOptions) + " options. They are: ")
# print(mChoice_options)
print("\nQuestion " + str(index + 1) + "/" + str(qasQsL) + ":")
for i in range(0, len(lines)):
print(lines[i])
# answer = ""
answer = input(">")
# answer = input(qas_keys[index]+ ": ")
if mChoiceQ == False:
if len(answer) > 0:
if answer.lower() == str(qas_vals[index]).lower():
return codes_answerCorrect
else:
incorrectResponses.append(qas_keys[index])
incorrectResponses_replies.append(answer)
# print("DEBUG: Incorrect response! Expected '" + str(qas_vals[index]).lower() + "', received " + answer.lower())
return codes_answerIncorrect
else:
print("Please insert an answer!")
else:
allowedResponse = False
for i in range(0, len(mChoice_options)):
if answer.lower() == mChoice_options[i].lower():
allowedResponse = True
if allowedResponse == True:
ans = qas_vals[index].lower()
yn = False
ans_yesno = ""
if ans.lower() == "y" or ans.lower() == "n":
yn = True
else:
yn = False
if yn == True:
if ans == "y":
ans_yesno = "yes"
elif ans == "n":
ans_yesno = "no"
if len(answer) > 0:
if yn == True:
if answer.lower() == ans.lower() or answer.lower() == ans_yesno.lower():
return codes_answerCorrect
else:
return codes_answerIncorrect
incorrectResponses.append(qas_keys[index])
incorrectResponses_replies.append(answer)
else:
if answer.lower() == ans.lower():
return codes_answerCorrect
else:
return codes_answerIncorrect
incorrectResponses.append(qas_keys[index])
incorrectResponses_replies.append(answer)
else:
print("Please insert an answer!")
else:
print("Invalid response! You may only enter the following: " + str(mChoice_options))
def saveScore():
# Clear file!
score_file_CLEAR = open("SCORES.txt", "wt")
score_file_CLEAR.close()
# Save contents
score_file = open("SCORES.txt", "wt")
for i in range(0, len(SCORE_SET)):
score_file.write(SCORE_SET[i])
print("Done saving!")
def btnPressed(tmp):
print(tmp)
app = App()
while True:
qasQsL = len(qasSequenced)
if gameOn == True and selectedMode != modes_err:
if qasQsSequenced == True:
if qasINDEX < qasQsL:
answerCode = quizController(qasINDEX)
else:
output = randomize(qasQsL)
if output == "0":
qasQsSequenced = True
if qasINDEX < qasQsL:
if answerCode == codes_answerCorrect:
score += 1
qasINDEX += 1
# print("DEBUG: Correct! Score set to: " + str(score))
elif answerCode == codes_answerIncorrect:
if selectedMode == modes_hard:
score -= 1
qasINDEX += 1
# print("Score set to: " + str(score))
else:
print("")
if qasQsL != 0:
score_per = score / qasQsL
if score_per < 0:
score_per = 0
if score < 0:
score = 0
print("You score was lower than 0, therefore it was set to 0")
# print("Your score: " + str(score) + "/" + str(len(qasSequenced)) + " (" + str(int(score_per*100)) + "%)")
# if score != qasQsL:
# print("You responded to the following questions incorrectly:")
# print(incorrectResponses)
if score / qasQsL == 1:
SCORE_SET.append(quiztaker_name + " scored " + str(score) + " out of " + str(qasQsL) + "(" + str(
int(score / qasQsL) * 100) + "%). PART OF Qs: " + str(
int(randQs)) + " at division factor 1/" + str(qasQsL_divisionFactor) + ", MODE: " + str(
int(selectedMode)) + "\n")
if score / qasQsL != 1:
SCORE_SET.append(quiztaker_name + " scored " + str(score) + " out of " + str(qasQsL) + " (" + str(
int(score / qasQsL) * 100) + "%). PART OF Qs: " + str(
int(randQs)) + " at division factor 1/" + str(qasQsL_divisionFactor) + ", MODE: " + str(
int(selectedMode)) + " They got the following questions wrong: \n")
for i in range(0, len(incorrectResponses)):
SCORE_SET.append(" " + str(i + 1) + ") " + incorrectResponses[i] + " --RESPONSE-- " +
incorrectResponses_replies[i] + "\n")
SCORE_SET.append("\n")
saveScore()
qasQsSequenced = False
gameOn = False
print("\nGame over!")
askReplay = True
else:
continue
elif askReplay == False:
TEMP = input("What mode would you like? (E = Easy, H = Hard): ")
if len(str(TEMP)) > 0:
if str(TEMP).lower() == "e":
selectedMode = modes_ez
gameOn = True
print("Set mode to: NO POINT DEDUCTIONS")
elif str(TEMP).lower() == "h":
selectedMode = modes_hard
gameOn = True
print("Set mode to: POINT DEDUCTIONS ALLOWED")
else:
print("Error: Undefined response. Please try again!")
elif askReplay == True:
TEMP = input("Would you like to (re)do the quiz? (Y/N): ")
if len(str(TEMP)) > 0:
if str(TEMP).lower() == "y":
askReplay = False
qasQsSequenced = False
qasQsL = 0
qas.clear()
qasSequenced.clear()
qasTmp.clear()
qasINDEX = 0
incorrectResponses.clear()
answerCode = err_noCode
score = 0
selectedMode = modes_err
importAndClean()
randQs = False
USER_TEMP = input("Please enter your name >")
if len(USER_TEMP) > 0:
quiztaker_name = str(USER_TEMP)
print("Welcome " + quiztaker_name + "!")
USER_TEMP = input("Would you like all questions (a) or a part of the questions(p)? (A/P) > ")
if len(USER_TEMP) > 0:
if USER_TEMP.lower() == "a":
print("Set to all questions!")
randQs = False
elif USER_TEMP.lower() == "p":
print("Set to 1/" + str(qasQsL_divisionFactor) + " questions (pre-set variable)")
randQs = True
else:
print("Undefined response! Setting to default value (ALL)")
randQs = False
gameOn = False
askReplay = False
elif str(TEMP).lower() == "n":
selectedMode = modes_hard
gameOn = False
print("Exiting now!")
saveScore()
sleep(2)
exit(0)
else:
print("Error: Undefined response. Please try again!")
Entry() doesn't work like input(). It doesn't wait for your data but it only informs tkitner that you want to display Entry widget (and mainloop() will display it) and Python goes to next lines of code and it runs print(str(answerField.get())) before it even displays window - so you try to get from empty Entry.
You should get it in function assigned to Button which you will press after you put some text in Entry.
The same problem is with
lambda arg1=self.answerField.get():print(arg1)
it assigns to args value from Entry only once when lambda is defined at start - so it get empty string. You should use it inside function
command=lambda:print(self.answerField.get())
or create normal function and assign to button.
Minimal working code
import tkinter as tk
import threading
class App(threading.Thread):
def run(self):
self.root = tk.Tk()
#self.root.protocol("WM_DELETE_WINDOW", self.on_close)
self.answerField = tk.Entry(self.root)
self.answerField.grid(row=0, column=1)
#b = tk.Button(self.root, text='Show', command=lambda:print(self.answerField.get()))
b = tk.Button(self.root, text='Show', command=self.on_click)
b.grid(row=1, column=1)
self.root.mainloop()
def on_click(self):
print(self.answerField.get())
#def on_close(self):
# self.root.destroy()
App().start()
#App().run()

How to update tkinter labels that are stored in a list, using a button?

I need to update a list of labels that could be any size. All questions I've found already dealt in single labels instead of lists. I tried to extrapolate those answers to my problem and have not been successful.
I tried associating the list of labels with a list of StringVars and was not successful.
import nation
import game_time
def main():
Ven = nation.Nation("Venice", 1500000, 60, 5)
Mil = nation.Nation("Milan", 1250000, 10, 5)
Flo = nation.Nation("Florence", 7500000, 90, 5)
game_time.pass_time(1)
print ("test")
for n in nation.Nation._registry:
print (n.get_pop_stats())
if __name__ == '__main__':
main()
#NATION
name = ""
population = 0
econ_value = 0
owned_land = 0
GROWTH = .002
MONTH_GROWTH = .002/12
current_growth = 0
expected_growth = 0;
class Nation:
_registry = []
def __init__(self, name = "dummy", population = -1, econ_value = -1, owned_land = -1):
self.name = name
self.population = population
self.econ_value= econ_value
self.owned_land = owned_land
self._registry.append(self)
def get_pop_stats(self):
return "Nation: " + self.name + " Population: " + str(self.population) + " Current Growth: " + str(self.current_growth) + " Expected Growth: " + str(self.expected_growth) + "\n"
#TIME
import nation
GROWTH = .002
MONTH_GROWTH = .002/12
def pass_time(x):
while x > 0:
for p in nation.Nation._registry:
temp = p.population
p.population += p.population*(p.econ_value/100)*MONTH_GROWTH
p.current_growth = p.population - temp
p.expected_growth = p.population*(p.econ_value/100)*MONTH_GROWTH
x -= 1;
#ERROR
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.do_labels()
ran = 0
def do_labels(self):
pop_text = []
pop_stats = []
time = tk.Button(self, text="PASS TIME", fg="red", command= lambda: self.press())
time.pack(side="bottom")
i = 0
for n in nation.Nation._registry:
pop_text.append(tk.StringVar(value = n.get_pop_stats()))
pop_stats.append(tk.Label(self, textvariable = pop_text[i], command = print("initializing label")))
pop_stats[i].pack(side="top")
i+=1
self.ran = 1
self.pack()
root.update()
def press(self):
print("this works")
game_time.pass_time(1)
root = tk.Tk()
app = Application(master=root)
app.mainloop()
My bad, Here is the nation class, required to run the code.
Expected: Numbers in the labels update.
Actual: Nothing happens in the window, but the button successfully prints in the console.

How do I do time.sleep in certain thread in python

I'm trying to make a constant updater that adds 2 of a resource each second. The problem is, when I do time.sleep(1), it puts the whole program to sleep and if I don't put it, the program crashes.
def coins(self):
""" Creates the resource coins """
self.coins = 0
self.goldlabel = Label(self,text = str(self.coins) + " gold")
self.goldlabel.grid(row = 6, column = 0, columnspan = 1, sticky = W)
def residences(self):
self.residence = 0
def passivegold(self):
amount = self.residence
if self.residence > 0:
add = amount * 2
self.coins += add
# time.sleep(1)
self.goldlabel.configure(text = str(self.coins) + " gold")

Categories

Resources