I'm new to python so this code is a mess but I have found a bug I can't fix. The program is meant to give you maths sums to solve and I was using buttons that sent an int as a value from 1 to 4 then that is tested in the guess function to generate the next question. The problem is that the int is not changing when the buttons are pressed and every sum is an addition one because it is set as 1 in the root. If anyone could help that would be great, thanks in advance!
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from random import randint
def plus(*args):
op = 1
def minus(*args):
op = 2
def times(*args):
op = 3
def divide(*args):
op = 4
def guess(*args):
try:
numberguess = int(ans.get())
except ValueError:
ask.set('That is not a number!')
global number
gdif = number - numberguess
if gdif == 0:
ask.set('You got it right!')
global score
sco = score.get() + 1
score.set(sco)
result = messagebox.askquestion('', 'Next question')
if result == 'yes':
if top.get() == 0:
noone = randint(1,10)
notwo = randint (1,10)
else:
noone = randint(1,top.get())
notwo = randint(1,top.get())
ans_entry.focus()
if op == 1:
number = noone + notwo
numb.set('What is ' + str(noone) + ' + '+ str(notwo) + '?')
elif op == 2:
number = noone - notwo
numb.set('What is ' + str(noone) + ' - '+ str(notwo) + '?')
elif op == 3:
number = noone * notwo
numb.set('What is ' + str(noone) + ' x '+ str(notwo) + '?')
elif op == 4:
number = noone / notwo
numb.set('What is ' + str(noone) + ' / '+ str(notwo) + '?')
elif result == 'no':
root.destroy()
elif gdif>0:
ask.set(ans.get() + ' is too low')
elif gdif<0:
ask.set(ans.get() + ' is too high')
ans.set('')
root = Tk()
root.title('Maths Game') #window title
mainframe = ttk.Frame(root, padding = '3 3 12 12')
mainframe.grid(column = 0, row = 0, sticky = (N, W, E, S))
mainframe.columnconfigure(0,weight = 1)
mainframe.rowconfigure(0, weight = 1)
#organises grid well
ans = StringVar()
numb = StringVar()
ask = StringVar()
pts = StringVar()
score = IntVar()
top = IntVar()
#sets as variables
ans_entry = ttk.Entry(mainframe, width = 7, textvariable = ans) #defines guess entry
ans_entry.grid(column = 2, row = 1, sticky = (W, E)) #places guess entry on grid
ttk.Label(mainframe, textvariable = numb).grid(column = 2, row = 2, sticky = (W, E)) #label
ttk.Label(mainframe, textvariable = ask).grid(column = 3, row = 1, sticky = (W, E)) #label
ttk.Label(mainframe, textvariable = score).grid(column = 3, row = 2, sticky = (E)) #label
ttk.Label(mainframe, textvariable = pts).grid(column = 4, row = 2, sticky = (W, E))
ttk.Button(mainframe, text = 'Answer', command = guess).grid(column = 3, row = 3, sticky = (W, E)) #guess button
top_entry = ttk.Entry(mainframe, width = 3, textvariable = top)
top_entry.grid(column = 3, row = 4, sticky = (E))
ttk.Button(mainframe, text = '+', command = plus).grid(column = 1, row = 5, sticky = (W, E))
ttk.Button(mainframe, text = '-', command = minus).grid(column = 2, row = 5, sticky = (W, E))
ttk.Button(mainframe, text = 'x', command = times).grid(column = 3, row = 5, sticky = (W, E))
ttk.Button(mainframe, text = '/', command = divide).grid(column = 4, row = 5, sticky = (W, E))
for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5) #pads grid nicely
ans_entry.focus() #cursor starts in box
root.bind('<Return>', guess) #binds entry key to guess button
noone = randint(1,10)
notwo = randint (1,10)
number = noone + notwo
numb.set('What is ' + str(noone) + ' + '+ str(notwo) + '?')
right = False
sco = 0
score.set(sco)
pts.set(' points')
one = 10
op = 1
root.mainloop() #launches main code
Because op is a local variable in every function.
You should add global op:
def plus(*args):
global op
op = 1
.
.
.
But be aware that this is a very sub-optimal way of doing it.
It makes much more sense to have a class, then have these functions as its methods. That way they will all have access to the op variable without it having to be a global.
Related
I am doing a coding where I need to program different math flashcards and the user has to answer them. But when answering them, the message keeps saying the same number and not updating the new numbers that it is supposed to get.
from tkinter import messagebox
from random import randint
def clicked():
messagebox.showinfo('Rules of the Game', '1. You are going to be provided with basic arithmetic (Adding, Subtracting, Multiplying)'
'\n2. You are going to answer them'
'\n3. Based on the answer you gave, it will keep track of the correct and incorrect answers including how many in total you have answered')
root = Tk()
root.title('Math Flash Cards')
root.geometry('900x500')
Title = Label(root, text="Title", font=('Arial', 30))
Title.grid(row = 0, column = 4)
Rule_btn = Button(root, text="Click Here for Rules", font=('Arial'), command=clicked)
Rule_btn.grid(row = 3, column = 4)
#Create random flashcard numbers
def math_random():
global nums
number_1 = randint(1,10)
number_2 = randint(1,10)
add_1.configure(text = number_1)
add_2.configure(text = number_2)
def answer_add():
answers = number_1 + number_2
if int(add_ans.get()) == answers:
response = 'Correct ' + str(number_1) + ' + ' + str(number_2) + ' = ' + str(answers)
elif int(add_ans.get()) != answers:
response = 'Wrong! ' + str(number_1) + ' - ' + str(number_2) + ' = ' + str(answers)
answer_message.config(text = response)
add_ans.delete(0, 'end')
math_random()
global nums
number_1 = randint(1,10)
number_2 = randint(1,10)
global add_1
global add_2
add_1 = Label(root, text='+', font=('Arial', 20))
add_2 = Label(root, text='+', font=('Arial', 20))
math_operator = Label(root, text='+', font=('Arial', 20))
add_1.grid(row = 5, column = 3)
math_operator.grid(row = 5, column = 4)
add_2.grid(row = 5, column = 5)
add_1.configure(text = number_1)
add_2.configure(text = number_2)
global add_ans
add_ans = Entry(root, font = ('Arial', 14))
add_ans.grid(row = 7, column = 4)
add_ans_btn = Button(root, text ='Click', font = ('Arial'), command= answer_add)
add_ans_btn.grid(row = 7, column = 5)
global answer_message
answer_message = Label(root, text='Type you answer with the provided space above', font=('Arial'))
answer_message.grid(row = 10, column = 4)
What should I do to make it update? I kept making changes to the code, but it is not changing when the numbers are changing.
I have all the gui configurations and all that stuff in my main.py and my algorithms to draw bubble sort and merge sort in another .py file. I'm trying to write the print functions into my canvas but I'm not sure how to do it, can anyone help? I tried using a ListBox() but it messes up the main canvas for some reason.
This is my code for my main file:
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from bubbleSort import bubbleSort
from mergeSort import mergeSort
tk = Tk()
tk.title('Examen Final')
tk.maxsize(900, 600)
tk.config(bg = 'black')
algoritmo = StringVar()
data = []
def dibujar(data, color):
c.delete("all")
cHeight = 380
cWidth = 600
algoWidth = cWidth / (len(data) + 1)
algoHeight = cWidth / (len(data) + 1)
offset = 20
spacing = 10
tamData = [i / max(data) for i in data]
for i, height in enumerate(tamData):
x0 = i * algoWidth + offset + spacing
y0 = cHeight - height * 50
x1 = (i+1) * algoWidth + offset
y1 = cHeight
c.create_oval(x0,y0,x1,y1, fill = color[i])
c.create_text(x0+2,y0, anchor = SW, text=str(data[i]))
tk.update_idletasks()
def Ordenar():
print("Se selecciono: " + algoritmo.get())
print("Iniciando algoritmo")
global data
if menu.get() == 'MERGE SORT':
mergeSort(data, dibujar)
elif menu.get() == 'BUBBLE SORT':
bubbleSort(data, dibujar)
dibujar(data, ['green' for x in range(len(data))])
def agregar():
global data
input = int(inputVal.get())
inputVal.delete(0, END)
try:
print("valor input:")
print(input)
data.append((input))
print(str(data))
dibujar(data, ['red' for x in range(len(data))])
except:
messagebox.showerror("Error", "Ingrese un valor numerico")
def limpiar():
global data
data = []
c.delete("all")
print(data)
box = Frame(tk, width = 600, height = 200, bg = 'black' )
box.grid(row = 0, column = 0, padx=10, pady=5)
c = Canvas(tk, width = 600, height = 380, bg = 'grey')
c.grid(row = 1, column = 0, padx=10, pady=5)
c2 = Canvas(tk, width = 200, height = 380, bg = 'grey')
c2.grid(row = 1, column = 1, padx=10, pady=5)
label = Label(box, text='Lista Algoritmos: ', font = ("Arial",15), borderwidth=1, bg = "black" , fg = 'white')
label.grid(row=0,column=0, padx=5, pady=5, sticky = W)
menu = ttk.Combobox(box, textvariable = algoritmo, values=['BUBBLE SORT', 'MERGE SORT', 'HASH TABLES', 'ARBOL AVL', 'ARBOLES ROJO Y NEGRO'])
menu.grid(row=0, column=1, padx=5, pady=5)
menu.current(0)
botonStart = Button(box, text = 'Ordenar', command = Ordenar, bg = 'lime green')
botonStart.grid(row = 0, column = 2, padx = 5, pady = 5)
label = Label(box, text='Insertar valor: ', font = ("Arial",15), borderwidth=1, bg = "black" , fg = 'white')
label.grid(row=1,column=0, padx = 5, pady = 5, sticky = W)
inputVal = Entry(box)
inputVal.grid(row=1,column=1, padx = 5, pady = 5, sticky = W)
botonAdd = Button(box, text = 'Agregar', command = agregar, bg = 'lime green')
botonAdd.grid(row = 1, column = 2, padx = 5, pady = 5, sticky = W)
botonClear = Button(box, text = 'Limpiar', command = limpiar, bg = 'lime green')
botonClear.grid(row = 1, column = 3, padx = 5, pady = 5, sticky = W)
tk.mainloop()
and this is my bubbleSort.py
import time
def bubbleSort(data, dibujar):
for _ in range(len(data)-1):
for j in range(len(data)-1):
if data[j] > data[j+1]:
print(("El numero " + str(data[j]) + " es mayor que " + str(data[j+1])))
data[j],data[j+1] = data[j+1], data[j]
print(("Intercambiando de lugar " + str(data[j]) + " con " + str(data[j+1])))
dibujar(data,
[
'green'
if x == j or x == j+1
else 'red' for x in range(len(data))
]
)
time.sleep(1)
dibujar(data, ['green' for x in range(len(data))])
You can just pass in c2 to the function on the other file. So first define the parameter:
def bubbleSort(data, dibujar, cnv):
cnv.create_text(100,100,text='Trial Text')
....
Now each time you call this function, pass on c2 to it.
if menu.get() == 'BUBBLE SORT':
bubbleSort(data, dibujar, c2)
I did notice that you are using dynamic points for calculation, if so, make those points global, inside the function, then pass those onto the function by creating more parameter, while keeping in mind that the points have to defined before the function is called.
I've tried to search this topic up, but it has been very confusing, as I don't use/quite understand stdout/stderr... However, I have this code right now that prints a list onto the console. Can someone explain to me how I could get this to print directly onto a GUI Textbox? My code:
from tkinter import *
import math
class TimeGenerator:
def __init__(self,master):
frame = Frame(master)
frame.grid()
label_iso = Label(root, text="Isotope A, Element")
label_vol = Label(root, text="Voltage")
label_range = Label(root, text="Charge Range")
entry_iso = Entry(root)
entry_vol = Entry(root)
entry_range = Entry(root)
label_iso.grid(row=0, sticky=E)
label_vol.grid(row=1, sticky=E)
label_range.grid(row=2, sticky=E)
entry_iso.grid(row=0, column=1)
entry_vol.grid(row=1, column=1)
entry_range.grid(row=2,column=1)
button = Button(root, text='Time Range', command=self.calculateTime)
button.grid(row=3, columnspan=2)
self.iso = entry_iso
self.vol = entry_vol
self.r = entry_range
def calculateTime(self):
x = 5
self.iso = self.iso.get().replace(" ", "")
list = []
for e in self.iso.split(","):
list.append(e)
f = open("/Users/LazyLinh/PycharmProjects/mass.mas12.txt", "r")
i = 0
while (i < 40):
header = f.readline()
i += 1
self.mass = 0
for line in f:
line = line.strip()
columns = line.split()
if (list[0] == columns[3]):
if (list[1] == columns[4]):
if (len(columns) == 16):
self.mass = float(columns[13].replace("#","")) + float(columns[14].replace("#",""))
else:
self.mass = float(columns[12].replace("#","")) + float(columns[13].replace("#",""))
self.r = self.r.get().replace(" ", "")
tup = tuple(int(x) for x in self.r.split(","))
list = []
for q in range(tup[0], tup[1] + 1):
y = x * math.sqrt(self.mass / (2 * q * float(self.vol.get())))
list.append(y)
i = tup[0]
for time in list:
print(i, ':', time)
i = i + 1
root = Tk()
b = TimeGenerator(root)
root.mainloop()
Thank you!
Somewhere in your code you need to create a text widget:
class TimeGenerator:
def __init__(self,master):
...
self.text = Text(...)
...
Later, use the insert method of the text widget instead of a print statement:
for time in list:
self.text.insert("end", "%d: %s\n" % (i, time))
i = i + 1
I wrote this program and was trying to learn TKinter GUI. I get no errors when I run the program and it looks good with the GUI, I then enter the values in the boxes and hit calculate button and nothing happens, I would like to find out why nothing is put in the result label at the bottom of the GUI.
Thanks for any help.
from tkinter import *
from tkinter import ttk
def calculate(*args):
try:
if elevud.get() == 'u':
elev = float(elevation.get()) / 3
dist = float(distance.get()) + elev
else:
elev = float(elevation.get()) / 3
dist = float(distance.get()) - elev
if windfb.get() == 'f':
w = float(wind.get()) * 1.75
dist = dist + w
else:
w = float(wind.get()) * 0.75
dist = dist - w
newDistance.set(dist)
except ValueError:
pass
root = Tk()
root.title("TGC Disctance Calculator")
mainframe = ttk.Frame(root, padding = "3 3 12 12")
mainframe.grid(column = 0, row = 0, sticky = (N, W, E, S))
mainframe.columnconfigure(0, weight = 1)
mainframe.rowconfigure(0, weight = 1)
distance = StringVar()
elevation = StringVar()
wind = StringVar()
windfb = StringVar()
elevud = StringVar()
newDistance = StringVar()
distance_entry = ttk.Entry(mainframe, width = 7, textvariable = distance)
distance_entry.grid(column = 2, row = 1, sticky = (W, E))
elevation_entry = ttk.Entry(mainframe, width = 7, textvariable = elevation)
elevation_entry.grid(column = 2, row = 2, sticky = (W, E))
elevud_entry = ttk.Entry(mainframe, width = 7, textvariable = elevud)
elevud_entry.grid(column = 2, row = 5, sticky = (W, E))
wind_entry = ttk.Entry(mainframe, width = 7, textvariable = wind)
wind_entry.grid(column = 2, row = 3, sticky = (W, E))
windfb_entry = ttk.Entry(mainframe, width = 7, textvariable = windfb)
windfb_entry.grid(column = 2, row = 4, sticky = (W, E))
ttk.Label(mainframe, text = "Distance").grid(column = 1, row = 1, sticky = W)
ttk.Label(mainframe, text = "Elevation").grid(column = 1, row = 2, sticky = W)
ttk.Label(mainframe, text = "Up or Down [u/d]").grid(column = 1, row = 3, sticky = W)
ttk.Label(mainframe, text = "Wind Speed").grid(column = 1, row = 4, sticky = W)
ttk.Label(mainframe, text = "Wind Direction [f/b]").grid(column = 1, row = 5, sticky = W)
ttk.Button(mainframe, text = "Calculate", command = calculate).grid(column = 2, row = 6, sticky = W)
ttk.Label(mainframe, text = "Corrected Distance ").grid(column = 1, row = 7, sticky = W)
ttk.Label(mainframe, textvariable = newDistance).grid(column = 2, row = 7, sticky = E)
for child in mainframe.winfo_children(): child.grid_configure(padx = 5, pady = 5)
distance_entry.focus()
root.bind('<Enter>', calculate)
root.mainloop()
Somehow you got the positioning of your text boxes mixed up. elevud should be in row 3, not row 5; and so on.
distance_entry = ttk.Entry(mainframe, width = 7, textvariable = distance)
distance_entry.grid(column = 2, row = 1, sticky = (W, E))
elevation_entry = ttk.Entry(mainframe, width = 7, textvariable = elevation)
elevation_entry.grid(column = 2, row = 2, sticky = (W, E))
elevud_entry = ttk.Entry(mainframe, width = 7, textvariable = elevud)
elevud_entry.grid(column = 2, row = 3, sticky = (W, E))
wind_entry = ttk.Entry(mainframe, width = 7, textvariable = wind)
wind_entry.grid(column = 2, row = 4, sticky = (W, E))
windfb_entry = ttk.Entry(mainframe, width = 7, textvariable = windfb)
windfb_entry.grid(column = 2, row = 5, sticky = (W, E))
As it was originally, entering "u" in the third text box would cause wind to be "u" rather than elevud, which would cause float(wind.get()) to crash because "u" can't be converted to a float. Note that it's easier to debug these sorts of things if you don't pass when you encounter an exception.
Incidentally, <Enter> doesn't trigger whenever the enter key is pressed. It triggers whenever the mouse cursor enters the boundaries of a widget. Were you thinking of <Return>?
I am making a maths test using tkinter. I have 4 entries to allow the user to input the answers of questions. the answers must be in integer format if not it will give a long error. I wanted my program to check if the inputted value is an integer or not.and then if it is not an integer open up a message box telling the user to check the answers.
here is my code: (it's a long code because I didn't know how to shorten it, I'm not a programmer)
from tkinter import*
from tkinter import messagebox
from random import*
n1= randint(1,6)
n2= randint(1,9)
ques1 = n1, "x", n2, "="
c1= n1*n2
n1= randint(8,15)
n2= randint(1,7)
ques2 = n1, "-", n2, "="
c2= n1-n2
n1= randint(1,10)
n2= randint(5,15)
ques3 = n1, "+", n2, "="
c3= n1+n2
n1= randint(5,12)
n2= randint(1,10)
ques4 = n1, "x", n2, "="
c4= n1*n2
#window
window = Tk()
window.geometry("280x450")
window.title("quiz")
window.configure(background='yellow')
def checkthrough():
if ans1.get() == '':
messagebox.showinfo("error", "check again ")
elif ans2.get() == '':
messagebox.showinfo("error", "check again ")
elif ans3.get() == '':
messagebox.showinfo("error", "check again ")
elif ans4.get() == '':
messagebox.showinfo("error", "check again ")
else:
save()
#this is where i tried to check if it's an integer or not
try:
ans1 == int()
except:
messagebox.showinfo("error", "check again ")
def save():
score = 0
if c1==int(ans1.get()):
score= score + 1
if c2==int(ans2.get()):
score = score+1
if c3==int(ans3.get()):
score = score+1
if c4==int(ans4.get()):
score = score+1
fscore.set(score)
def savetofile():
result = result ="\n "+ namestudent.get() + " " + fscore.get()+"/4"
messagebox.showinfo("results", "your results been saved successfuly")
if int(year.get())==1:
f = open('results C1.txt', 'a')
f.write(result)
f.close()
if int(year.get())==2:
f = open('results C2.txt', 'a')
f.write(result)
f.close()
if int(year.get())==3:
f = open('results C3.txt', 'a')
f.write(result)
f.close()
#frame
frame = Frame(window)
frame.columnconfigure(0, weight=1)
frame.rowconfigure(0, weight=1)
#variables
namestudent = StringVar()
ans1 = StringVar()
ans2 = StringVar()
ans3 = StringVar()
ans4 = StringVar()
fscore = StringVar()
year = StringVar()
#labels
name = Label(window, text = "type your name:")
name.grid(row= 6, column = 0)
yr = Label(window, text = "type your class:")
yr.grid(row= 7, column = 0)
q1 = Label(window,text = ques1, height = 3, bg = 'yellow')
q1.grid(row = 1,column=0)
q2 = Label(window,text = ques2, height = 3, bg = 'yellow')
q2.grid(row = 2,column=0)
q3 = Label(window,text = ques3, height = 3, bg = 'yellow')
q3.grid(row = 3,column=0)
q4 = Label(window,text = ques4, height = 3, bg = 'yellow')
q4.grid(row = 4,column=0)
#entrys
name_entry= Entry(window, textvariable= namestudent)
name_entry.grid(row = 6, column=1)
yr_entry= Entry(window, textvariable= year)
yr_entry.grid(row = 7, column=1)
q1_entry = Entry(window, width = 6, textvariable = ans1)
q1_entry.grid(row = 1,column=1)
q2_entry = Entry(window, width = 6, textvariable = ans2)
q2_entry.grid(row = 2,column=1)
q3_entry = Entry(window, width = 6, textvariable = ans3)
q3_entry.grid(row = 3,column=1)
q4_entry = Entry(window, width = 6, textvariable = ans4)
q4_entry.grid(row = 4,column=1)
#buttons
finish = Button(window, width = 5, text = "finish",command= checkthrough)
finish.grid(row = 5,column=0)
finalS_label = Label(window, textvariable=fscore)
finalS_label.grid(row=5, column=1)
saving = Button(window, width = 5, text = "save", command= savetofile)
saving.grid(row= 8, column=0)
window.mainloop()
I read some other post about the same question and I tried to use their answers in my code but still I'm getting the same error.
thanks.
In order to check if a string is integer-convertible, just try converting it and check for exceptions.
try:
integer_result = int(string_result)
except ValueError:
print("not a valid integer")
else:
print("value is", integer_result)
To do this in your case, you want to extract the values from ans1 &c. beforehand, then pass the raw strings to int().