tkinter - How to set one Checkbutton opposite of other? - python-3.x

I am trying to set the value of one checkbox to always be the opposite of the other using tkinter (python3.5). I want it to be so that when ever the user click on one of the Checkbuttons, the other button is always changed to the opposite value.
What am I doing wrong? I cant work it out.
from tkinter import *
def opposite(buttonA):
print("running Opposite")
if buttonA.get() == 0:
buttonB.set(1)
elif buttonA.get() == 1:
buttonB.set(0)
root = Tk()
buttonA=IntVar()
buttonA.set(1)
buttonAchk = Checkbutton(root, variable=buttonA)
buttonAchk.pack()
buttonAlabel = Label(root, width=30, text="Button A")
buttonAlabel.pack()
buttonB=IntVar()
buttonB.set(0)
buttonBCheck = Checkbutton(root, variable=opposite(buttonA))
buttonBCheck.pack()
buttonBlabel = Label(root, width=30, text="Button B")
buttonBlabel.pack()
root.mainloop()

Maybe use, Radiobutton instead?
from tkinter import *
root = Tk()
buttonA=IntVar()
R1 = Radiobutton(root, text="Button A", width = 30, variable=buttonA, value=1)
R1.pack()
R2 = Radiobutton(root, text="Button B", width = 30, variable=buttonA, value=0)
R2.pack()
root.mainloop()

Related

All other widgets are affected when one of the widgets move in a GUI (using the tkinter library in python 3)

Whenever I try to move individual widgets or click a button that produces words effectively moving other widgets that had nothing to do those both specified actions above.
Here is my code:
import tkinter as tk
# Create the main window
window = tk.Tk()
window.title("Price Calculator")
window.geometry("800x600")
window.config(background = "#777474")
def calculate_price():
global input_field
input_field_value = input_field.get()
try:
input = int(input_field_value)
price = input* 0.1
answer.config(text = (f"Your price is ","%.3f"%price,"KWD"))
except ValueError as ve:
answer.config(text = 'What you have just entered are not numbers whatsoever, try again!', fg = "#CD5F66")
price_input = tk.Label(window, text = "Total Pages:", font = "Arial", bg = "#777474", fg = "#FEFCF2")
price_input.grid(column = 0, row = 0)
input_field = tk.Entry(window, font = "Arial", bg = "#FEFCF2")
input_field.grid(column = 1, row = 0, padx = 0,pady = 10)
answer = tk.Label(window, bg = "#777474")
answer.grid(pady = 20)
button_return = tk.Button(window, text = "Calculate Price", command = calculate_price).grid()
# Run the main loop
window.mainloop()
This is my GUI before I click on the button which is called "Calculate Price":
This is my GUI after I have clicked on the button:
The problem here is that I don't want the Total Pages and the entry field to move away from each other whenever I click on the button.
I would suggest to put price_input and input_field into a frame for easier layout management. I also use sticky="w" on the frame, answer and button_return so that they are aligned at the left.
Below is the modified code:
import tkinter as tk
FGCOLOR = "#FEFCF2"
BGCOLOR = "#777474"
ERRCOLOR = "#FF5F66"
# Create the main window
window = tk.Tk()
window.title("Price Calculator")
window.geometry("800x600")
window.config(background="#777474")
def calculate_price():
input_field_value = input_field.get()
try:
input = int(input_field_value)
price = input * 0.1
answer.config(text=f"Your price is {price:.3f} KWD", fg=FGCOLOR)
except ValueError as ve:
answer.config(text='What you have just entered are not numbers whatsoever, try again!', fg=ERRCOLOR)
# create a frame for price_input and input_field
frame = tk.Frame(window, bg=BGCOLOR)
frame.grid(column=0, row=0, padx=10, pady=10, sticky="w")
price_input = tk.Label(frame, text="Total Pages:", font="Arial", bg=BGCOLOR, fg=FGCOLOR)
price_input.grid(column=0, row=0)
input_field = tk.Entry(frame, font="Arial", bg=FGCOLOR)
input_field.grid(column=1, row=0)
answer = tk.Label(window, bg=BGCOLOR)
answer.grid(column=0, row=1, padx=10, pady=10, sticky="w")
button_return = tk.Button(window, text="Calculate Price", command=calculate_price)
button_return.grid(column=0, row=2, sticky="w", padx=10, pady=10)
# Run the main loop
window.mainloop()

Tkinter dialog's elements position

I am building custom Tkinter dialog window with Entry and Combobox. I am stuck with placing text and enter frames. Currently I am placing them manually. I am looking for the way to let tkinter do it automatically (maybe with pack() method). And also configure TopLevel size automatically.
My code:
def ask_unit_len():
values = ['millimeters', 'micrometers', 'nanometers']
top = Toplevel()
top.geometry('170x100')
top.resizable(False, False)
top.focus_set()
top.grab_set()
top.title('Enter length and units')
label_length = Label(top, text='Length:')
label_length.place(x=0, y=0)
units_type = StringVar()
length = StringVar()
answer_entry = Entry(top, textvariable=length, width=10)
answer_entry.place(x=55, y=0)
label_units = Label(top, text='Units:')
label_units.place(x=0, y=30)
combo = Combobox(top, width=10, textvariable=units_type,
values=values)
combo.place(x=50, y=30)
button = Button(top, text='Enter',
command=lambda:
mb.showwarning("Warning",
"Enter all parameters correctly")
if (units_type.get() == "" or not length.get().isdigit()
or int(length.get()) <= 0)
else top.destroy())
button.place(x=65, y=70)
top.wait_window(top)
return int(length.get()), units_type.get()
So, is there any way to perform this?

Using Tkinter to disable entry with specified input

I would like to use Tkinter to be able to disable one entry if 'no' is selected from a drop down menu.
from tkinter import *
def disableEntry(entry):
entry.config(state='disable')
def allowEntry(entry):
entry.config(state='normal')
def main():
print("test")
root = Tk() #create a TK root window
root.title("Lunch and Learn") #Title of the window
L1 = Label(root, text = "Label 1").grid(row=0, column=0, padx=30, pady=(20,5))
L2 = Label(root, text = "Label 2").grid(row=1, column=0, pady=5)
var = StringVar()
E1 = Entry(root,bd =3)
E1.grid(row=0, column=1)
D1 = OptionMenu(root,var,"yes","no")
D1.grid(row=1,column=1)
if var.get() == 'no':
disableEntry(E1)
elif var.get() == 'yes':
allowEntry(E1)
B2 = Button(text = "Submit", command=main).grid(row=4, column=2)
root.mainloop()
the above code is a simple example of what i have tried. I have created two functions called 'disableEntry' and 'allowEntry' which should change the state of the entry box but they don't appear to do anything when i change the input of the drop down menu.
i dont know if i am approaching this the wrong way or if there is a standardized way to do this.
any help would be appreciated.
You need a way to check the state of the selection after it is changed. That can be achieved with adding a callback command to the OptionMenu widget.
You were checking the correct variable, but the point you were checking it at was before the screen window had even displayed.
from tkinter import Label, StringVar, OptionMenu, Entry, Tk, Button
# change the state of the Entry widget
def change_state(state='normal'):
E1.config(state=state)
def main():
print("test")
# callback function triggered by selecting from OptionMenu widget
def callback(*args):
if var.get() == 'no':
change_state(state='disable')
elif var.get() == 'yes':
change_state(state='normal')
root = Tk() #create a TK root window
root.title("Lunch and Learn") #Title of the window
L1 = Label(root, text="Label 1").grid(row=0, column=0, padx=30, pady=(20, 5))
L2 = Label(root, text="Label 2").grid(row=1, column=0, pady=5)
var = StringVar()
E1 = Entry(root, bd=3)
E1.grid(row=0, column=1)
D1 = OptionMenu(root, var, "yes", "no", command=callback)
D1.grid(row=1, column=1)
B2 = Button(text = "Submit", command=main).grid(row=4, column=2)
root.mainloop()

How to activate tkinter window after destroying the previously one?

I need the next tkinter window to become active automatically after destroying the previous one.
I'm working with Python 3 in Windows 10.
import sys
from tkinter import *
#Green button pressed
def passed():
fails='0'
with open("ButtonPressed.txt",'w')as TestResult:
TestResult.write(fails)
TestResult.close()
root.destroy()
#Red button pressed
def failed():
fails='1'
with open("ButtonPressed.txt",'w')as TestResult:
TestResult.write(fails)
TestResult.close()
root.destroy()
#First window
def PushHold(UUT):
global root
root = Tk()
root.bind('<Return>', lambda q:passed())
TitleText="Push Button test"
root.title(TitleText)
root.geometry("460x160")
frame = Frame(root)
frame.pack()
bottomframe = Frame(root)
bottomframe.pack( side = BOTTOM )
LABLE_TEXT = "Push and hold S1 on "+ UUT+" board.\n Click OK."
label = Label( frame, text=LABLE_TEXT)
label.config(font=("Arial", 22))
label.pack( side = TOP)
greenbutton = Button(frame, text="OK", bg="Green", fg="White", height=2 , width = 10 , command=lambda: passed())
greenbutton.config(font=("Arial", 18))
greenbutton.pack( side = LEFT, padx=140)
root.mainloop()
#Second window
def Release(UUT):
global root
root = Tk()
root.bind('<Return>', lambda q:passed())
TitleText="Release Button test"
root.title(TitleText)
root.geometry("460x160")
frame = Frame(root)
frame.pack()
bottomframe = Frame(root)
bottomframe.pack( side = BOTTOM )
LABLE_TEXT = "Release S1 on "+ UUT+" board.\n Click OK."
label = Label( frame, text=LABLE_TEXT)
label.config(font=("Arial", 22))
label.pack( side = TOP)
greenbutton = Button(frame, text="OK", bg="Green", fg="White", height=2 , width = 10 , command=lambda: passed())
greenbutton.config(font=("Arial", 18))
greenbutton.pack( side = LEFT, padx=140)
root.mainloop()
#read results of the first window
def PushButton(UUT):
PushHold(UUT)
with open("ButtonPressed.txt",'r') as TestResult:
str = list(TestResult)
fails = int(str[0])
TestResult.close()
return fails
#read results of the second window
def ReleaseButton(UUT):
Release(UUT)
with open("ButtonPressed.txt",'r') as TestResult:
str = list(TestResult)
fails = int(str[0])
TestResult.close()
return fails
PushButton('UUT1') #first window calling
ReleaseButton('UUT1') #second window calling
The first window is working good, the second window appears, but not active. It is necessary to click on it to activate before pressing the button.
Trials to use root.withdraw() or root.lift() did not succeed.
On my system the second window takes focus without altering your code, so it is hard to tell. You could probably use root.focus_force() prior to calling root.mainloop()
Alternatively, you could spawn different windows from the same root, using tk.Toplevel.
import sys
from tkinter import *
#Green button pressed
def passed():
fails='0'
with open("ButtonPressed.txt",'w')as TestResult:
TestResult.write(fails)
TestResult.close()
root.destroy()
#Red button pressed
def failed():
fails='1'
with open("ButtonPressed.txt",'w')as TestResult:
TestResult.write(fails)
TestResult.close()
root.destroy()
#First window
def PushHold(UUT):
global root
root = Tk()
root.bind('<Return>', lambda q:passed())
TitleText="Push Button test"
root.title(TitleText)
root.geometry("460x160")
frame = Frame(root)
frame.pack()
bottomframe = Frame(root)
bottomframe.pack( side = BOTTOM )
LABLE_TEXT = "Push and hold S1 on "+ UUT+" board.\n Click OK."
label = Label( frame, text=LABLE_TEXT)
label.config(font=("Arial", 22))
label.pack( side = TOP)
greenbutton = Button(frame, text="OK", bg="Green", fg="White", height=2 , width = 10 , command=lambda: passed())
greenbutton.config(font=("Arial", 18))
greenbutton.pack( side = LEFT, padx=140)
root.focus_force() #<-------------- Here ---------------------
root.mainloop()
#Second window
def Release(UUT):
global root
root = Tk()
root.bind('<Return>', lambda q:passed())
TitleText="Release Button test"
root.title(TitleText)
root.geometry("460x160")
frame = Frame(root)
frame.pack()
bottomframe = Frame(root)
bottomframe.pack( side = BOTTOM )
LABLE_TEXT = "Release S1 on "+ UUT+" board.\n Click OK."
label = Label( frame, text=LABLE_TEXT)
label.config(font=("Arial", 22))
label.pack( side = TOP)
greenbutton = Button(frame, text="OK", bg="Green", fg="White", height=2 , width = 10 , command=lambda: passed())
greenbutton.config(font=("Arial", 18))
greenbutton.pack( side = LEFT, padx=140)
root.focus_force() #<-------------- Here ---------------------
root.mainloop()
#read results of the first window
def PushButton(UUT):
PushHold(UUT)
with open("ButtonPressed.txt",'r') as TestResult:
str = list(TestResult)
fails = int(str[0])
TestResult.close()
return fails
#read results of the second window
def ReleaseButton(UUT):
Release(UUT)
with open("ButtonPressed.txt",'r') as TestResult:
str = list(TestResult)
fails = int(str[0])
TestResult.close()
return fails
PushButton('UUT1') #first window calling
ReleaseButton('UUT1') #second window calling

How to make Tkinter button open in the same windows like in many other programs

I have a program calculator, the button code opens a new window, but I want the button calculator run in the same window but not two separate, how do I instead run my code in the same windows?
P.S. the code is not mine, it is as an example
from tkinter import *
root = Tk()
root.title("Math Lab")
root.geometry("1400x1000")
heading = Label(root, text = "Welcome to the MATH Lab", font=("Berlin Sans FB", 40, "bold"), fg= "steelblue").pack()
root.configure(background= "powder blue")
def calculator():
w = Tk()
w.geometry("1400x1000")
def evaluate1():
res.configure(text="Answer: " + str(eval(entry.get())))
def evaluate(event):
res.configure(text="Answer: " + str(eval(entry.get())))
but1 = Button(w, text="Enter", width=10, height=3)
but1.place(x=650, y=100)
but1.config(command=evaluate1)
Label(w, text="Your Expression:").pack()
entry = Entry(w)
entry.bind("<Return>", evaluate)
entry.pack()
res = Label(w)
res.pack()
w.mainloop()
but1=Button(root,text="Calculator",width = 10, height = 3)
but1.place(x=100, y=100)
but1.config(command = calculator)
root.mainloop()
Any suggestions?
Here you are requesting a new window:
w = Tk()
Replace it with
w = root
and you are good to go.
(Well, you'll want to tidy up some x,y offsets, for aesthetics.)

Resources