Need help switch labels when button pressed in tkInter - python-3.x

I need it so that when I press the button it will switch between 2 labels, when I have managed to create a second statement now I need to be able to switch between the two. I have no clue what to do to get this to work, please help
def changeLabelText():
z = True
print(z)
if z == True:
print("The current text is", l1['text'])
z = False
return z
elif z == False:
print("The current text is", l12['text'])
z = True
return z
l1['text'] = "Changed Text"
l12['text'] = "Text"
b1 = Button(app, text="Change Text", command=changeLabelText)
l1 = Label(app, text="Text")
l12 = Label(app, text="New Text")

It's unclear for what reason you're using those redundant conditions, but here's a small example how you can switch labels (technically - a text options as your function's name claims):
try:
import tkinter as tk
except ImportError:
import Tkinter as tk
def changeLabelText():
l1['text'], l2['text'] = l2['text'], l1['text']
app = tk.Tk()
b1 = tk.Button(app, text="Change Text", command=changeLabelText)
l1 = tk.Label(app, text="Text")
l2 = tk.Label(app, text="New Text")
l1.pack()
l2.pack()
b1.pack()
app.mainloop()

Related

Can't create a if statement with a entry widget and a random integer for my function

I am new to tkinter and python, I ran into a problem during my if statements. I am trying to compare the entries to the randomly imported integers and delete the page and give a congrats screen.
I have tried to create text variable but I didn't know how to define it and I was sent to use get command but I'm stuck here now.
I would really appreciate any help and thank you for your time.
I am new to tkinter and python, I ran into a problem during my if statements. I am trying to compare the entries to the randomly imported integers and delete the page and give a congrats screen. I would really appreciate any help and thank you for your time.
from math import *
from tkinter import *
from tkinter import messagebox
# Intro Window Creation
window = Tk()
window.geometry("900x500")
window.title("Welcome To Practice Your Quadratic Equation Solving Skills")
# Picking Difficulty
def Introclick():
window.destroy()
windo = Tk()
windo.geometry("900x500")
windo.title("Difficulty Setting")
label1 = Label(windo, text="Please enter your difficulty setting from ranging 1-3", bg="gray", font="Georgia 22")
label1.pack()
lebel2 = Label(windo, text="1 being the easiest and 3 being the hardest", bg="gray")
lebel2.pack()
def LV1():
def destroy1():
lOL.destroy()
lOL=Tk()
Answer11=Entry(lOL)
Answer12=Entry(lOL)
Answer11.pack()
Answer12.pack()
def crap():
if y > x:
if Answer11.get() == y and Answer12.get() == x:
lOL.destroy()
response = messagebox.askyesno("Great job you got it", "Try again")
else:
print("cry1")
else:
if Answer11.get() == x and Answer12.get() == y:
lOL.destroy()
response = messagebox.askyesno("Great job you got it", "Try again")
else:
print("cry2")
lOL.geometry("900x500")
lOL.title("Level 1")
z = Label(lOL, text="Easiest Difficulty")
z.pack()
lOL.configure(bg="gray")
import random
x = random.randint(1,5)
y = random.randint(1,7)
b = x + y
c = x * y
FunctionOut1=Label(lOL, text="Quadratic Equation \n" +"x^2 + " + str(b) + "x + " + str(c), bg="gray", fg="green" )
FunctionOut1.pack()
Dead = Button(lOL, text="Exit", command=destroy1)
Dead.pack()
LAB11 = Label(lOL, text="Input both Answers, Integers Only")
LAB11.pack()
FAnswer1=Button(lOL, command=crap,text="Submit Answer")
FAnswer1.pack()
# The buttons that allow to pick the difficulty
B1 = Button(windo,text="Level 1", width=(20), command=LV1, fg="green", bg="gray")
B2 = Button(windo,text="Level 2", width=(20), command=LV2, fg="yellow", bg="gray")
B3 = Button(windo,text="Level 3", width=(20), command=LV3, fg="red", bg="gray")
B1.pack()
B2.pack()
B3.pack()
windo.configure(bg="gray")
Introbutt = Button(window, text="Let's Start!", padx=50, pady=50, command=Introclick, fg="blue", bg="black")
Introbutt.pack()
window.mainloop()

How can i bind from one function to another in python

Im trying to make my code bind to red only at first
and make red's handler rebind to yellow after red finishes. Im not sure how to do this. Would anyone know how this is done. Because in my code if you run it. It only runs the yellow function instead of red and im pretty sure this is because im overwriting the bind function.
from tkinter import *
import random
root = Tk()
root.geometry("300x300")
score = 0
lb1 = Listbox(root)
e = Entry(root)
def binder1():
root.bind('<Return>', red)
def red(event):
print(e.get())
if e.get() == "red":
lb1.insert("end", "Correct")
binder1
global score
score += 1
mb4['text'] = str("Score ") + str(score)
redcolour = Label(root, text = "What colour is this boi!", fg = "Red")
def yellow(event):
print(e.get())
if e.get() == "yellow":
lb1.insert("end", "Correct")
global score
score += 1
mb4['text'] = str("Score ") + str(score)
root.bind('<Return>', yellow)
yellowcolour = Label(root, text = "What colour is this boi!", fg = "Yellow")
mb4= Menubutton(root, text = str("Score: ") + str(score))
mb4.menu = Menu(mb4)
e.focus_set()
e.pack()
yellowcolour.pack()
redcolour.pack()
lb1.pack()
mb4.pack()
root.mainloop()
It's not clear for me why you want to bind red first.
I would make it more dynamically and let make decision by user input.
like this:
from tkinter import *
def check_input(event):
global score
my_input = e.get()
if my_input == "yellow":
lb1.insert("end", "Correct yellow")
score += 1
mb4['text'] = str("Score ") + str(score)
elif my_input == "red":
lb1.insert("end", "Correct red")
score += 1
mb4['text'] = str("Score ") + str(score)
else:
return None
if __name__ == "__main__":
root = Tk()
root.geometry("300x300")
root.bind('<Return>', check_input)
score = 0
lb1 = Listbox(root)
e = Entry(root)
redcolour = Label(root, text = "What colour is this boi!", fg = "Red")
yellowcolour = Label(root, text = "What colour is this boi!", fg = "Yellow")
mb4= Menubutton(root, text = str("Score: ") + str(score))
e.focus_set()
e.pack()
yellowcolour.pack()
redcolour.pack()
lb1.pack()
mb4.pack()
root.mainloop()

updating python3 tkinter label not working

I can manually update label and entry if i clicked the manual button, but if i clicked the auto button... the console show the random number but the widgets are not updating.
from tkinter import *
import random
import time
def manual_settxt():
for t in range(0,3):
rd = random.randrange(1,100)
labelWidgets[t].configure(text=rd)
entryWidgets[t].delete(0,END)
entryWidgets[t].insert(0,rd)
def auto_settxt():
while True:
time.sleep(3)
for t in range(0,3):
rd = random.randrange(1,100)
print(rd)
labelWidgets[t].configure(text=rd)
entryWidgets[t].delete(0,END)
entryWidgets[t].insert(0,rd)
root = Tk()
namesInput = [1,2,3]
entryWidgets = []
labelWidgets = []
for i in range(0, len(namesInput)):
labelWidgets.append(Label(root,text=namesInput[i],justify='center'))
entryWidgets.append(Entry(root,width=5,justify='center'))
labelWidgets[-1].grid(row=i+1,column=0)
entryWidgets[-1].grid(row=i+1,column=1)
b1 = Button(root, text = "Manual", command=manual_settxt)
b1.grid(row=4,column=0)
b2 = Button(root, text = "Auto", command=auto_settxt)
b2.grid(row=4,column=1)
root.mainloop()
You created an infinite loop. Delete while True.
I refactored some code: used Thread for non-blocking functionality.
Try this
from tkinter import *
import random
import time
from threading import Thread
def manual_settxt():
for index in range(3):
rd = random.randrange(1,100)
labelWidgets[index].configure(text=rd)
entryWidgets[index].delete(0,END)
entryWidgets[index].insert(0,rd)
def job():
for index in range(3):
time.sleep(1)
rd = random.randrange(1,100)
print(rd)
labelWidgets[index].configure(text=rd)
entryWidgets[index].delete(0,END)
entryWidgets[index].insert(0,rd)
def auto_settxt():
Thread(target=job).start()
root = Tk()
namesInput = [1,2,3]
entryWidgets = []
labelWidgets = []
for index, name in enumerate(namesInput):
labelWidgets.append(Label(root, text=name, justify='center'))
entryWidgets.append(Entry(root, width=5, justify='center'))
labelWidgets[-1].grid(row=index+1,column=0)
entryWidgets[-1].grid(row=index+1,column=1)
b1 = Button(root, text = "Manual", command=manual_settxt)
b1.grid(row=4,column=0)
b2 = Button(root, text = "Auto", command=auto_settxt)
b2.grid(row=4,column=1)
root.mainloop()
I use "root.after" and the script seems to be working fine.
from tkinter import *
import random
import time
def manual_settxt():
for index in range(3):
rd = random.randrange(1,100)
labelWidgets[index].configure(text=rd)
entryWidgets[index].delete(0,END)
entryWidgets[index].insert(0,rd)
def auto_settxt():
for index in range(3):
rd = random.randrange(1,100)
print(rd)
labelWidgets[index].configure(text=rd)
entryWidgets[index].delete(0,END)
entryWidgets[index].insert(0,rd)
root.after(1000, auto_settxt)
root = Tk()
namesInput = [1,2,3]
entryWidgets = []
labelWidgets = []
for index, name in enumerate(namesInput):
labelWidgets.append(Label(root, text=name, justify='center'))
entryWidgets.append(Entry(root, width=5, justify='center'))
labelWidgets[-1].grid(row=index+1,column=0)
entryWidgets[-1].grid(row=index+1,column=1)
b1 = Button(root, text = "Manual", command=manual_settxt)
b1.grid(row=4,column=0)
b2 = Button(root, text = "Auto", command=auto_settxt)
b2.grid(row=4,column=1)
root.after(1000, auto_settxt)
root.mainloop()

Tkinter entry boxes

I need to count from a starting input value to an ending value using tkinter entry boxes but the 2 output files are blank except for brackets and I know that the csv outputs work it's just getting the user input that is the issue. Thanks for any help.
There is the current code.
import csv
from tkinter import *
# Variables/Arrays
oddArray = []
evenArray = []
def main():
for i in range(oute1, oute2):
x = i
# Odds
if(x % 2 == 1):
oddArray.append(x)
# Evens
elif(x % 2 == 0):
evenArray.append(x)
with open("odd_labels", "w") as outputFile1:
writer1 = csv.writer(outputFile1)
writer1.writerow([oddArray])
with open("even_labels", "w") as outputFile2:
writer2 = csv.writer(outputFile2)
writer2.writerow([evenArray])
# gui framework
myGui = Tk()
# myGui.geometry('225x50')
# myGui.title("Label Creator")
Label(myGui, text="Starting value: ").grid(row=0)
Label(myGui, text="Ending value: ").grid(row=1)
a = IntVar()
b = IntVar()
e1 = Entry(myGui, textvariable=a).grid(row=0, column=1)
e2 = Entry(myGui, textvariable=b).grid(row=1, column=1)
oute1 = a.get()
oute2 = b.get()
Button(myGui, text="Start", command=main).grid(row=3)
myGui.mainloop()
The problem is how you create your entry fields.
When you use the grid manager at the end of a widget creation then you are unable to use .get() on it because the grid manager is returning None. To avoid this you need to make sure you create your widget first then define where it goes on a separate line.
Change:
e1 = Entry(myGui, textvariable=a).grid(row=0, column=1)
e2 = Entry(myGui, textvariable=b).grid(row=1, column=1)
to:
e1 = Entry(myGui, textvariable=a)
e1.grid(row=0, column=1)
e2 = Entry(myGui, textvariable=b)
e2.grid(row=1, column=1)
I notived your oute1 and oute2 are both only created on the start of the program. You need to move them into a function and it should work fine in your main function.
Try this:
import csv
from tkinter import *
myGui = Tk()
oddArray = []
evenArray = []
Label(myGui, text="Starting value: ").grid(row=0)
Label(myGui, text="Ending value: ").grid(row=1)
a = IntVar()
b = IntVar()
e1 = Entry(myGui, textvariable=a)
e1.grid(row=0, column=1)
e2 = Entry(myGui, textvariable=b)
e2.grid(row=1, column=1)
def main():
oute1 = a.get()
oute2 = b.get()
for i in range(oute1, oute2):
x = i
# Odds
if(x % 2 == 1):
oddArray.append(x)
# Evens
elif(x % 2 == 0):
evenArray.append(x)
with open("odd_labels", "w") as outputFile1:
writer1 = csv.writer(outputFile1)
writer1.writerow([oddArray])
with open("even_labels", "w") as outputFile2:
writer2 = csv.writer(outputFile2)
writer2.writerow([evenArray])
Button(myGui, text="Start", command=main).grid(row=3)
myGui.mainloop()

After text widget opens, tkinter GUI crashes/does not respond whenever its closed

Right now, after I press the 'Time Range' button and call the calculateTime function, the text widget would appear with the results that I've inserted into it. However, after that, whenever I close the GUI window, the program would freeze and I'll have to forced quit it. This is my code:
import tkinter
from tkinter import *
import math
from tkinter import messagebox
class MyClass(tkinter.Frame):
def __init__(self, *args, **kwargs):
tkinter.Frame.__init__(self, *args, **kwargs)
#Setting up frame and widgets
vcmd1 = (self.register(self.__vcmd1), '%P', '%S')
vcmd2 = (self.register(self.__vcmd2), '%P')
vcmd3 = (self.register(self.__vcmd3), '%P', '%S')
label_iso = Label(self,text="Isotope A, Element")
label_vol = Label(self, text="Voltage")
label_range = Label(self, text="Charge Range")
label_iso.grid(row=0, column=0, sticky=E)
label_vol.grid(row=1, column=0, sticky=E)
label_range.grid(row=2, column=0, sticky=E)
self.entry1 = tkinter.Entry(self, validate="key", validatecommand=vcmd1)
self.entry2 = tkinter.Entry(self, validate="key", validatecommand=vcmd2)
self.entry3 = tkinter.Entry(self, validate="key", validatecommand=vcmd3)
self.entry1.grid(row=0, column=1)
self.entry2.grid(row=1, column=1)
self.entry3.grid(row=2, column=1)
def __vcmd1(self, P, S):
validString = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM,1234567890'
if not S in validString:
return False
if "," in P:
if (len(P) - 1) > len(P.replace(",","")):
return False
messagebox.showinfo("Error", "Expected Form: ex. 133,Cs")
else:
return True
def __vcmd2(self, P):
if P == '':
return True
try:
float(P)
return True
except ValueError:
messagebox.showinfo("Error", "Entry is not a float or integer")
return False
def __vcmd3(self, P, S):
if "," in P:
if len(P.split(",")) > 2:
return False
a = P.split(",")[0]
b = P.split(",")[1]
if a != '' and b != '':
try:
int(a)
int(b)
except ValueError:
messagebox.showinfo("Error", "Expected form: ex. 1,12")
return False
else:
return True
class TimeGenerator:
def __init__(self,master):
frame = MyClass(master)
frame.grid(columnspan=2)
button = Button(root, text='Time Range', command=self.calculateTime)
button.grid(row=3, columnspan=2)
self.text = Text(root)
self.iso = frame.entry1
self.vol = frame.entry2
self.r = frame.entry3
def calculateTime(self):
x = 5
if self.r.get() == "" or self.iso.get() == "" or self.vol.get() == "":
messagebox.showinfo("Error", "No field can be empty")
return None
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
#iterate through text file
for line in f:
line = line.strip()
columns = line.split()
if (list[0] == columns[3]):
if (list[1].lower() == columns[4].lower()):
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("#",""))
#Calculation
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 * 1.6605402e-27 / (2 * q * float(self.vol.get())))) * 10e6
list.append(y)
i = tup[0]
#inserting to text widget
for time in list:
self.text.insert("end", "%d: %s\n" % (i, time))
i = i + 1
self.text.pack()
root = Tk()
b = TimeGenerator(root)
root.mainloop()
I've tried to searched up on this topic, but I'm not really using any weird update() function, and text shows up after the function is finished, so how likely that it is an event loop problem? Am I also doing something wrong that could cause this problem?
Thank you!
You have widgets in the root window that use both pack and grid. You cannot do this. Within a given container (root window, frame, etc) you can use one or the other, but not both.
The reason your program freezes is due to pack and grid fighting to gain control of the layout. When you pack the text widget it causes a change in the size and/or position of other widgets in the root window. That triggers grid to try to re-layout the widgets it is responsible for. This triggers pack to try to re-layout the widgets it is responsible for, and on and on until the end of time.
My guess is that you need to use grid with self.text since you use grid everywhere else.

Resources