In Croatia we have competitions where you make apps. I'm making an app to help 1st and 2nd graders learn and revise math. I just started recently so it doesn't have almost anything. The problem is that when variable: mode = "number" , entries aren't placed. Btw when opening the app you will be presented with 4 options. They are addition, subtraction, multiplication and division. I translated it from Croatian to English so you can understand. When you run the program press the Addition button. Then you will see the task but entries missing. If you change the value of the variable mode to mode = "result", entries are placed. I tried everything but couldn't get it to work.
Here's the code:
import tkinter as tk
import random
wn = tk.Tk()
wn.config(width = 550, height = 500)
wn.resizable(False, False)
wn.title("Learn and Revise")
number1_1 = 0
number1_2 = 0
number2_1 = 0
number2_2 = 0
number3_1 = 0
number3_2 = 0
number4_1 = 0
number4_2 = 0
number5_1 = 0
number5_2 = 0
def makeRandomNumbers():
global number1_1, number1_2
global number2_1, number2_2
global number3_1, number3_2
global number4_1, number4_2
global number5_1, number5_2
if mode == "number":
while True:
number1_1 = random.randint(0, 10)
number1_2 = random.randint(0, 10)
if number1_1 > number1_2:
pass
else:
break
while True:
number2_1 = random.randint(0, 10)
number2_2 = random.randint(0, 10)
if number2_1 > number2_2:
pass
else:
break
while True:
number3_1 = random.randint(0, 10)
number3_2 = random.randint(0, 10)
if number3_1 > number3_2:
pass
else:
break
while True:
number4_1 = random.randint(0, 10)
number4_2 = random.randint(0, 10)
if number4_1 > number4_2:
pass
else:
break
while True:
number5_1 = random.randint(0, 10)
number5_2 = random.randint(0, 10)
if number5_1 > number5_2:
pass
else:
break
elif mode == "result":
number1_1 = random.randint(0, 10)
number1_2 = random.randint(0, 10)
number2_1 = random.randint(0, 10)
number2_2 = random.randint(0, 10)
number3_1 = random.randint(0, 10)
number3_2 = random.randint(0, 10)
number4_1 = random.randint(0, 10)
number4_2 = random.randint(0, 10)
number5_1 = random.randint(0, 10)
number6_2 = random.randint(0, 10)
def placeTasks(oper):
global operation
operation = oper
makeTasks()
wipeMenu()
button_check.place(x = 310, y = 225)
label1.place(x = 150, y = 125)
label2.place(x = 150, y = 175)
label3.place(x = 150, y = 225)
label4.place(x = 150, y = 275)
label5.place(x = 150, y = 325)
if mode == "number":
entry1.place(x = 240, y = 130)
entry2.place(x = 240, y = 180)
entry3.place(x = 240, y = 230)
entry4.place(x = 240, y = 280)
entry5.place(x = 240, y = 330)
elif mode == "result":
entry1.place(x = 240, y = 130)
entry2.place(x = 240, y = 180)
entry3.place(x = 240, y = 230)
entry4.place(x = 240, y = 280)
entry5.place(x = 240, y = 330)
task1 = 0
task2 = 0
task3 = 0
task4 = 0
task5 = 0
def makeTasks():
global task1, task2, task3, task4, task5
global label1, label2, label3, label4, label5
makeRandomNumbers()
operation_sign = ""
if operation == "addition":
operation_sign = '+'
elif operation == "subtraction":
operation_sign = '-'
elif operation == "multiplication":
operation_sign = '•'
elif operation == "division":
operation_sign = '÷'
if mode == "result":
task1 = "{} {} {} =".format(number1_1, operation_sign, number1_2)
task2 = "{} {} {} =".format(number2_1, operation_sign, number2_2)
task3 = "{} {} {} =".format(number3_1, operation_sign, number3_2)
task4 = "{} {} {} =".format(number4_1, operation_sign, number4_2)
task5 = "{} {} {} =".format(number5_1, operation_sign, number5_2)
elif mode == "number":
task1 = "{} {} = {}".format(number1_1, operation_sign, number1_2)
task2 = "{} {} = {}".format(number2_1, operation_sign, number2_2)
task3 = "{} {} = {}".format(number3_1, operation_sign, number3_2)
task4 = "{} {} = {}".format(number4_1, operation_sign, number4_2)
task5 = "{} {} = {}".format(number5_1, operation_sign, number5_2)
label1 = tk.Label(wn, text = task1, font = ("Arial", 15))
label2 = tk.Label(wn, text = task2, font = ("Arial", 15))
label3 = tk.Label(wn, text = task3, font = ("Arial", 15))
label4 = tk.Label(wn, text = task4, font = ("Arial", 15))
label5 = tk.Label(wn, text = task5, font = ("Arial", 15))
operation = ""
mode = "number"
button_check = tk.Button(wn, width = 20, text = "Check")
label1 = tk.Label(wn, text = task1, font = ("Arial", 15))
entry1 = tk.Entry(wn, width = 7)
label2 = tk.Label(wn, text = task2, font = ("Arial", 15))
entry2 = tk.Entry(wn, width = 7)
label3 = tk.Label(wn, text = task3, font = ("Arial", 15))
entry3 = tk.Entry(wn, width = 7)
label4 = tk.Label(wn, text = task4, font = ("Arial", 15))
entry4 = tk.Entry(wn, width = 7)
label5 = tk.Label(wn, text = task5, font = ("Arial", 15))
entry5 = tk.Entry(wn, width = 7)
def placeMenu():
menu_label1.place(x = 175, y = 75)
button1.place(x = 200, y = 150)
button2.place(x = 200, y = 200)
button3.place(x = 200, y = 250)
button4.place(x = 200, y = 300)
def wipeMenu():
menu_label1.destroy()
button1.destroy()
button2.destroy()
button3.destroy()
button4.destroy()
menu_label1 = tk.Label(wn, text = "Revise", font = ("Arial", 35))
button1 = tk.Button(wn, width = 20, text = "Addition", command = lambda: placeTasks("addition"))
button2 = tk.Button(wn, width = 20, text = "Subtraction")
button3 = tk.Button(wn, width = 20, text = "Multiplication")
button4 = tk.Button(wn, width = 20, text = "Division")
placeMenu()
wn.mainloop()
Postavi font
prilikom inicijalizacije entrya, preimenuj if
statement i ukloni globalnu varijablu te koristi lokalnu (oper)
Prvo što vidim je mnoštvo ponavljanja. Napravi funkciju s više parametara na kojima ćeš izvršavati for
loopove - kod će biti kraći i čitljiviji 20 puta. Tkinter je jednostavan, ali nije praktičan ukoliko nije objektno orijentiran (preporučujem tk.Toplevel klase za prebacivanje prozora, onda samo switchaš screenove i nema potrebe za brisanjem i postavljanjem, što dodatno ubrzava izvrašavanje). Idealno bi bilo kreirati class
za svaku aritmetičku operaciju i uz to ne koristiti (spore) lambda anonimne funkcije samo za pozivanje s atributima.
Dakle, kod bi izgledao otprilike ovako:
for (akcija, klasa) in zip(["Addition", "Substraction", ...], lista_klasi):
button = tk.Button(wn, width=20, text=akcija, command=klasa);
...
button.pack() # Izbjegavaj .place(), uvijek samo pack() ili grid()
...
class Solution(tk.Toplevel):
def __init__(self, atributi):
super().__init__()
self.attributes("-topmost", False)
self.solution = tk.Canvas(self, bg="white" ...)
self.solution.pack()
...
# Za najbolji izgled postavljaj widgete na canvas...
self.solution.create_window(w, h, window=atribut[neki])
# Također, ako želiš ostati u istom prozoru, spremi widgete i koristi:
self.canvas.delete("all")
Osobno koristim pack jer je najjednostavniji, u početku nezgodan jer ne dobivaš izgledom točno kako zamišljaš ali kad pohvataš sve ne bi se nikad vratio na place(), osim ako nije nužno :)
Zasad prvo prouči sve pojašnjene primjere ovdje. Tek kad savladaš tkinter kreni na kivy ako misliš stvarno rasturit na natjecanju.