I have a check button that is checked by default. If the user unchecks it, a label and an entry should appear. I tried to do so by using the key binding method; however, it has a drawback which is that if the user checks the checkbox again, the new label and entry won't disappear. How do I solve that problem?
checkButtonVar = IntVar(value = 1)
checkButtonIsChnaceDefault = Checkbutton(root, variable = checkButtonVar)
labelIsChanceDefault = Label(root, text="Make chance = 0.9?")
labelIsChanceDefault.grid(row=3, column = 0, sticky = 'w')
checkButtonIsChnaceDefault.grid(row = 3, column = 1)
def checkCheckButton(event):
labelChance = Label(root, text = "Enter chance of winning")
labelChance.grid( row = 3, column = 2)
global entryChance
entryChance = Entry(root, borderwidth = 3)
entryChance.grid(row = 3, column = 3)
checkButtonIsChnaceDefault.bind('<Button-1>', checkCheckButton)
Here's a screenshot of the program to make things clear.
You don't need to bind the Check-button. Use command option. And setting offvalue and onvalue can control the appearance.
See the tkinter.Checkbutton
checkButtonVar = IntVar()
checkButtonIsChnaceDefault = Checkbutton(root, variable = checkButtonVar,offvvalue=0,onvalue=1,command=checkCheckButton)
...
checkButtonIsChnaceDefault.grid(row = 3, column = 1)
#==== Define the widgets here.
labelChance = Label(root, text = "Enter chance of winning")
entryChance = Entry(root, borderwidth = 3)
def checkCheckButton():
if checkButtonVar.get()==0:
labelChance.grid( row = 3, column = 2)
entryChance.grid(row = 3, column = 3)
else:
labelChance.grid_forget()
entryChance.grid_forget()
Related
I have created two check buttons and I want them both in row 5 and column 1. But I want the 'YES' check button to be formatted on the left side and the 'NO' check button to be on the right.
I have used sticky but it will not work. I also tried changing the width of the check buttons but this did not work either.
Do you have any suggestions?
Thank you!
self.yes_checkbtn = Checkbutton(self.entry_frame, width = 20, variable = checkbutton1,
anchor = W, text = "YES")
self.no_checkbtn = Checkbutton(self.entry_frame, width = 20, variable = checkbutton2,
anchor = E, text = "NO")
self.yes_checkbtn.grid(row = 5, column = 1, sticky = W)
self.no_checkbtn.grid(row = 5, column = 1, sticky = E)
Outcome:
I dont have enough points yet to show the image without a link - sorry
Put both check buttons under another new frame, then you can grid this new frame to column 1 of row 5, also change option width of Checkbutton to a small number, like 5.
Example code
from tkinter import *
root = Tk()
entry_frame = Frame(root)
entry_frame.grid(row=0, column=0)
for i in range(4):
for j in range(2):
label = Label(entry_frame, text=f'Row {i} Column {j}')
label.grid(row=i, column=j)
frame = Frame(entry_frame)
frame.grid(row=4, column=1)
checkbutton1 = BooleanVar()
checkbutton2 = BooleanVar()
yes_checkbtn = Checkbutton(frame, width = 5, variable = checkbutton1,
anchor = W, text = "YES", bg='green')
no_checkbtn = Checkbutton(frame, width = 5, variable = checkbutton2,
anchor = E, text = "NO", bg='blue')
yes_checkbtn.grid(row = 0, column = 1, sticky = W)
no_checkbtn.grid(row = 0, column = 2, sticky = W)
root.mainloop()
I'm using grid_remove() and grid() command to hide/show the widget but the result is the other widget is move out of the original position.
How to hide/show the widget without moving widget
Example:
from tkinter import *
from tkinter import ttk
GUI = Tk()
GUI.title("myTest")
GUI.geometry("700x700")
Nameget = StringVar()
Priceget = StringVar()
Quantityget = StringVar()
Unitget = StringVar()
Partnumget = StringVar()
L_Partnum = ttk.Label(GUI, text = 'Part number')
L_Partnum.grid(row = 0, column = 0)
L_namme = ttk.Label(GUI, text = 'Name')
L_namme.grid(row = 0, column = 1)
L_quan = ttk.Label(GUI, text = 'Quantity')
L_quan.grid(row = 1, column = 2)
L_quan.grid_remove()
L_price = ttk.Label(GUI, text = 'Price')
L_price.grid(row = 3, column = 3)
E_partnum = ttk.Entry(GUI, textvariable = Partnumget)
E_partnum.grid(row = 1, column = 0)
E_namme = ttk.Entry(GUI,textvariable = Nameget)
E_namme.grid(row = 1, column = 1)
E_unit = ttk.Entry(GUI,textvariable = Unitget)
E_quan = ttk.Entry(GUI,textvariable = Quantityget)
E_quan.grid(row = 2, column = 2)
E_quan.grid_remove()
E_price = ttk.Entry(GUI,textvariable = Priceget)
E_price.grid(row = 4, column = 3)
I_check_vat = IntVar()
def d_check_vat_1():
E_partnum.focus()
if I_check_vat.get() == 1:
L_quan.grid()
E_quan.grid()
elif I_check_vat.get() == 0:
L_quan.grid_remove()
E_quan.grid_remove()
C_CHECK_VAT = ttk.Checkbutton(GUI, text="click here to see the result", variable=I_check_vat, command=d_check_vat_1)
C_CHECK_VAT.grid(row = 5, column = 0)
GUI.mainloop()
Before clicking:
After clicking:
image with the expected output:
The problem is grid() does not take up empty space by default, it gives the last empty row/col to the widget(if previous rows before it are empty).
So what you can do is, set minimum space for your column and row so that those space will remain empty, so change your function to:
def d_check_vat_1():
E_partnum.focus()
if I_check_vat.get():
L_quan.grid(row=2, column=2)
E_quan.grid(row=3, column=2)
width = E_quan.winfo_reqwidth() # Get widget width
height = L_quan.winfo_reqheight() # Get widget height
GUI.rowconfigure(2,minsize=height) # Now apply the values
GUI.rowconfigure(3,minsize=height)
GUI.columnconfigure(2,minsize=width)
else:
L_quan.grid_remove()
E_quan.grid_remove()
Now its dynamic as well, it takes the width of widget and applies that as the minsize of that row so that row will have that empty space.
EDIT: I tried to edit it based on one suggestion that it needs to be tied to a function. But still not working properly. Thank you very much!
Hope you can help me. Saw related questions but not exactly the same. Thank you very much!
I have a radiobutton. Based on the selected value, the number of buttons will change. However, the number of buttons dont change. The number just based on the default value of the radiobutton (i tried changing it).
import tkinter
from tkinter import *
root = Tk()
TIME_SUBFRAME = root
#dont mind much this part, this is just the popup window that will show after I click the buttons dependent on the radiobutton
def month():
CAL_WINDOW = Toplevel(TIME_SUBFRAME) #other parts removed
#this is the part that I would want to be dependent on the radiobutton
ONLY_MONTH = Button(TIME_SUBFRAME, text='Month', command=month)
START_MONTH = Button(TIME_SUBFRAME, text='Start Month', command=month)
END_MONTH = Button(TIME_SUBFRAME, text='End Month', command=month)
def sing_month():
START_MONTH.destroy()
END_MONTH.destroy()
ONLY_MONTH.grid(row = 3, column = 2, columnspan = 2)
def mult_month():
ONLY_MONTH.destroy()
START_MONTH.grid(row = 3, column = 2)
END_MONTH.grid(row = 3, column = 3)
#Radiobuttons for timepoint selection type
YRTYPE = IntVar(TIME_SUBFRAME, 1)
SING_MONTH = Radiobutton(TIME_SUBFRAME, text = "Single Month", command = sing_month, variable = YRTYPE, value = 1)
MULT_MONTH = Radiobutton(TIME_SUBFRAME, text = "Multiple Months", command = mult_month, variable = YRTYPE, value = 2)
SING_MONTH.grid(row = 2, column = 2, padx = 10, pady = 10)
MULT_MONTH.grid(row = 2, column = 3, padx = 10, pady = 10)
root.mainloop()
The radiobutton numbers needs to checked their value when a function is called.You have declared checking statement in the current running block, which will return initial value of your radiobuttons.
The values needs to be checked when user checks the radiobutton.So, we need an extra button widget commanded with a function that checks the value of both radiobuttons and performs the related actions.
The radiobutton will not check the values automatically, it needs to be checked by function.
Here's your Solution,
import tkinter
from tkinter import *
root = Tk()
TIME_SUBFRAME = root
#dont mind much this part, this is just the popup window that will show after I click the buttons dependent on the radiobutton
def month():
CAL_WINDOW = Toplevel(TIME_SUBFRAME) #other parts removed
#this is the part that I would want to be dependent on the radiobutton
ONLY_MONTH = Button(TIME_SUBFRAME, text='Month', command=month)
START_MONTH = Button(TIME_SUBFRAME, text='Start Month', command=month)
END_MONTH = Button(TIME_SUBFRAME, text='End Month', command=month)
def sing_month():
START_MONTH.grid_remove()
END_MONTH.grid_remove()
ONLY_MONTH.grid(row = 3, column = 2, columnspan = 2)
def mult_month():
ONLY_MONTH.grid_remove()
START_MONTH.grid(row = 3, column = 2)
END_MONTH.grid(row = 3, column = 3)
#Radiobuttons for timepoint selection type
YRTYPE = IntVar(TIME_SUBFRAME, 1)
SING_MONTH = Radiobutton(TIME_SUBFRAME, text = "Single Month", command = sing_month, variable = YRTYPE, value = 1)
MULT_MONTH = Radiobutton(TIME_SUBFRAME, text = "Multiple Months", command = mult_month, variable = YRTYPE, value = 2)
SING_MONTH.grid(row = 2, column = 2, padx = 10, pady = 10)
MULT_MONTH.grid(row = 2, column = 3, padx = 10, pady = 10)
root.mainloop()
I am trying to make a program which calculates 3-4 values using some user inputted values
I have tried making a function which saves the entries into variables, and making the variables global but that didn't work
from tkinter import *
from math import *
root = Tk()
label1 = Label(root, text = "Enter value for length ")
label1.grid(columnspan = 2, sticky = "W")
length = Entry(root)
length.grid(row = 0, column = 2)
label2 = Label(root, text = "Enter value for volume ")
label2.grid(columnspan = 2, sticky = "W")
volume = Entry(root)
volume.grid(row = 1, column = 2)
label3 = Label(root, text = "Enter value for the thickness of the cylinder ")
label3.grid(columnspan = 2, sticky = "W")
thickness = Entry(root)
thickness.grid(row = 2, column = 2)
label4 = Label(root, text = "Enter value for starting temperature ")
label4.grid(columnspan = 2, sticky = "W")
st_T = Entry(root)
st_T.grid(row = 3, column = 2)
label5 = Label(root, text = "Enter value for finishing temperature ")
label5.grid(columnspan = 2, sticky = "W")
end_T = Entry(root)
end_T.grid(row = 4, column = 2)
def save():
v = volume.get()
l = length.get()
w = thickness.get()
t0 = st_T.get()
t1 = end_T.get()
global values
values = [v, l, w, t1, t0]
Button(root, text = "Submit", command = save).grid(row = 6, column = 0)
root.mainloop()
I know the current code isn't very pretty and is very inefficient but the error keeps saying that v is not defined
You might consider declaring a variable, or a an instance of a context object (that you will define) at global scope to store your user inputs.
Then you will be able to read the user inputs later in another function.
Do not forget to use the keyword 'global' before modifying the global object in a different scope (like in a function). Have a look here : https://www.geeksforgeeks.org/global-keyword-in-python/
By example you could declare your global object/variable/whatever you need, along with your root Tkinter object.
I've defined a class with a 'bpm' attribute:
class Section:
def __init__(self, id, bpm, bars, reps, num_tracks):
self.id = id
self.bpm = bpm
self.bars = bars
self.reps = reps
self.num_tracks = num_tracks
then I call the attribute to use it as the textvariable argument on a spinbox, once I've created an instance of my Section class, inside a dictionary:
def add_section():
new_id = next(itertools.count(1))
sections[new_id] = Section(new_id, 120, 1, 2, 1)
print((str(sections[new_id].bpm)))
sections[new_id].label_section_title = Label(root, text="Section {}".format(sections[new_id].id, relief = GROOVE))
sections[new_id].label_section_title.grid(row = 1, column = 4, columnspan = 5)
sections[new_id].label_bpm = Label(root, text="BPM: ")
sections[new_id].label_bpm.grid(row = 2, column = 4)
sections[new_id].bpm_control = Spinbox(root, from_ = 1, to = 999, textvariable = sections[new_id].bpm, command = lambda: sections[new_id].bpm_change(sections[new_id].bpm_control.get()))
sections[new_id].bpm_control.grid(row = 2, column = 5)
I'm able to print the value of sections[new_id].bpm as 120, so I know that works.
But even though I am setting textvariable on the spinbox, I'm just getting a value of 1 on the spinbox when I'd like it to be the 120 from the new instance. Even if I just set textvariable to straight up 120 I still just get a 1 there.
You need to set it as a IntVar() to use
self.bpm = IntVar()
self.bpm.set(bpm) # set value passed in
When getting the value from your spinbox you get either use Spinbox.get() which will return a string of the current value or self.bpm.get() which will be an int value