How to get values of checkbuttons from for loop tkinter python - python

I am new to programming in tkinter and am very stuck on using checkbuttons. I have created multiple checkbuttons in one go, all with different text for each one and a different grid position. However I have no idea how to get the value of each button or how to even set it. I want to be able to get the state/value for each button and if it is checked, then another function is called. How do I set and call the value/state of each button? Can this be done in a for loop or do I have to create them individually?
def CheckIfValid(self, window):
Class = self.ClassChosen.get()
Unit = self.UnitChosen.get()
Topic = self.TopicChosen.get()
if Class == '' or Unit == '' or Topic == '':
tm.showinfo("Error", "Please fill in all boxes")
else:
QuestionData = OpenFile()
QuestionsList = []
for x in range (len(QuestionData)):
#if QuestionData[x][2] == Topic:
QuestionsList.append(QuestionData[x][0])
for y in range(len(QuestionsList)):
self.ButtonVal[y] = IntVar()
Checkbutton(window, text = QuestionsList[y], padx = 20, variable = self.ButtonVal[y]).grid(row = 12 + y, column = 2)
ConfirmSelection = Button(window, text = "Set Homework", command = lambda: SetHomeworkClass.ConfirmHomework(self)).grid()
print(variable.get()) #here I would like to be able to get the value of all checkbuttons but don't know how

You use the list of IntVars either called from a command= in the Checkbutton or in the Button. Don't know why you are calling another class's object, SetHomeworkClass.objectConfirmHomework(self). It doesn't look like that will work as you have it programmed, as that is another name space and the list of IntVars is in this name space, but that is another topic for another thread.
try:
import Tkinter as tk # Python2
except ImportError:
import tkinter as tk # Python3
def cb_checked():
# remove text from label
label['text'] = ''
for ctr, int_var in enumerate(cb_intvar):
if int_var.get(): ## IntVar not zero==checked
label['text'] += '%s is checked' % cb_list[ctr] + '\n'
root = tk.Tk()
cb_list = [
'apple',
'orange',
'banana',
'pear',
'apricot'
]
# list of IntVar for each button
cb_intvar = []
for this_row, text in enumerate(cb_list):
cb_intvar.append(tk.IntVar())
tk.Checkbutton(root, text=text, variable=cb_intvar[-1],
command=cb_checked).grid(row=this_row,
column=0, sticky='w')
label = tk.Label(root, width=20)
label.grid(row=20, column=0, sticky='w')
# you can preset check buttons (1=checked, 0=unchecked)
cb_intvar[3].set(1)
# show what is initially checked
cb_checked()
root.mainloop()

Related

Where do I make a mistake with this tkinter focus?

I made a tool to add multiple order numbers in our system. The first time a row of entry cells is placed the focus is where it should be. But the second time the focus is not in the new left cell. First I thought it has to do with using the tab key. But if I understand the code correct, I first execute the moving of the tab key and then execute the code. So the command to focus on the new left cell is last.
Where am I going wrong?
import tkinter as tk
from tkinter import ttk
# Create variables for later use
order_list = []
date_list = []
row_number = 0
active_order_entry = None
active_date_entry = None
def add_a_row_of_entry_cells():
global row_number
global active_order_entry
global active_date_entry
row_number += 1
order_entry = ttk.Entry()
order_entry.grid(row=row_number, column=0)
order_entry.focus()
date_entry = ttk.Entry()
date_entry.grid(row=row_number, column=1)
# Make these entries the active ones
active_order_entry = order_entry
active_date_entry = date_entry
# Add entries to a list
order_list.append(order_entry)
date_list.append(date_entry)
def tab_pressed(event):
if active_order_entry.get() != "" and active_date_entry.get() != "":
add_a_row_of_entry_cells()
else:
print("Order, date or both are not filled yet")
def button_pressed():
print("Button pressed")
# Create window
window = tk.Tk()
# Add function to the Tab key
window.bind("<Tab>", tab_pressed)
# Labels on top of the columns
label_order_number = tk.Label(window, text="Order", fg="#22368C")
label_order_number.grid(row=row_number, column=0)
label_date = tk.Label(window, text="Date", fg="#22368C")
label_date.grid(row=row_number, column=1)
# Create empty row
empty_row = tk.Label(window)
empty_row.grid(row=87, column=0)
# Create button
button = tk.Button(window, text="Add orders", command=lambda: button_pressed())
button.grid(row=98, column=0, columnspan=3)
# Create empty row
empty_row = tk.Label(window)
empty_row.grid(row=99, column=0)
# Add the first row
add_a_row_of_entry_cells()
window.mainloop()

Tkinter Combobox dynamically set values

I'm attempting to set the options of a Tkinter Combobox dynamically. My code almost works, and I'm not sure why.
The code is designed to allow typing a string into an Entry box. It then searches through a list for any items that contain that string. So for example, if you type
Mi
into the entry box the list becomes
['Mickey', 'Minnie']
All this works as expected.
The Combobox [values] attribute is supposed to update whenever <FocusIn> is triggered using a function. This does indeed happen, but only after I click on the Combobox twice. I'm not sure why clicking on it the first time doesn't trigger the <FocusIn> binding. Is this the wrong binding? Is there something about my lambda function that isn't quite right? Would love some help!
Code:
from tkinter import *
from tkinter import ttk
init_list = ['Mickey', 'Minnie', 'Donald', 'Pluto', 'Goofy']
def db_values():
i = inp_var.get()
db_list = [x for x in init_list if i in x]
print(db_list)
return db_list
def db_refresh(event):
db['values'] = db_values()
root = Tk()
title_label = Label(root, text="Partial string example")
title_label.grid(column=0, row=0)
inp_var = StringVar()
input_box = Entry(root, textvariable=inp_var)
input_box.grid(column=0, row=1)
name_selected = StringVar()
db = ttk.Combobox(root, textvariable=name_selected)
db['values'] = db_values()
db.bind('<FocusIn>', lambda event: db_refresh(event))
db.grid(column=0, row=2, sticky=EW, columnspan=3, padx=5, pady=2)
root.mainloop()
def db_values():
i = inp_var.get()
db_list = [x for x in init_list if i in x]
print(db_list)
db['values'] = db_values()
Only this small Change is requires. list value must be assigned in the function itself.

tkinter - Changing variables assigned to labels causes duplicate window

I'm using python to interact with some excel spreadsheets. I have all that working and now I'm working on a UI using tkinter. I have 3 buttons one to pull the location of a data file, output file save location and I have a start button.
I'm trying to use a tkinter.Label to display the value of the first two buttons, example "c:/user/data_file". However, when ever I get the variable from the user and try to update the GUI with it, a copy of the window is created with the updated information. I need it to update directly to the current window seamlessly. I've been working to try to resolve this, but I just can't figure it out. Below is the code for my tkinter stuff.
def main():
def InputFilePrompt():
global InputFileLocation
InputFileLocation = askopenfilename()
update()
def OutputFilePrompt():
global OutputFileLocation
OutputFileLocation = filedialog.asksaveasfilename()
update()
def update():
root = Tk()
root.title("test")
root.resizable(width=TRUE,height=TRUE)
InputFile = Button(root, text = "input data", command = InputFilePrompt)
InputFile.grid(row = 0,column = 0)
InputFileValue = Label(root, text = InputFileLocation, bg = 'white')
InputFileValue.grid(row = 1,column = 0)
OutputFile = Button(root, text = "Compiled Data save loacation", command = OutputFilePrompt)
OutputFile.grid(row = 4,column = 0)
OutputFileValue = Label(root, text = "location: N/A", bg = 'white')
OutputFileValue.grid(row = 5,column = 0)
startButton = Button(root, text = "start", bg = 'light green', command = Excel)
startButton.grid(row = 7)
BlankUI = [0 for x in range(2)]
for blankspace in range(2):
BlankUI[blankspace] = Label(root, text = "")
BlankUI[0].grid(row = 2)
BlankUI[1].grid(row = 6)
root.mainloop()
update()
Error:
Here's a version that doesn't create the duplicate window. I've incorporated most of the suggestions I made in comments—except for the one about defining functions inside of other functions. The following still does this because doing so made it very easy to avoid using global variables (which are generally considered a poor programming practice).
Notice that there's no update() function. The values of the two tkinter.Labels are now being stored in two tkinter.StringVars objects instead of in regular Python strings. A StringVar is one of the tkinter so-called "Variable" classes. Their primary feature is that they will cause all widgets referencing them to automatically update themselves whenever their contents get changed. To use them in a Label, they're specified by using the textvariable= option (instead of the text= option) when the constructor is called.
Here's some documentation I found about them with more details on how they work.
import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename
def excel():
""" Undefined. """
pass
def main():
def get_input_file_location():
input_file_location.set(askopenfilename())
def get_output_file_location():
output_file_location.set(asksaveasfilename(confirmoverwrite=False))
root = tk.Tk()
root.title('test')
root.resizable(width=True, height=True)
input_file_location = tk.StringVar()
input_file_location.set('<undefined>')
output_file_location = tk.StringVar()
output_file_location.set('<undefined>')
input_file = tk.Button(root, text="Input data",
command=get_input_file_location)
input_file.grid(row=0, column=0)
input_file_value = tk.Label(root, textvariable=input_file_location,
bg='white')
input_file_value.grid(row=1, column=0)
output_file = tk.Button(root, text='Compiled data save loacation',
command=get_output_file_location)
output_file.grid(row=4, column=0)
output_file_value = tk.Label(root, textvariable=output_file_location,
bg='white')
output_file_value.grid(row=5, column=0)
startButton = tk.Button(root, text='start', bg='light green',
command=excel)
startButton.grid(row=7)
blank_ui = [tk.Label(root, text='') for _ in range(2)]
blank_ui[0].grid(row=2)
blank_ui[1].grid(row=6)
root.mainloop()
if __name__ == '__main__':
main()

Change label text on button using values from tuple click tkinter

I have a list of strings sorted in a tuple like this:
values = ('1.Python','2.Ruby','3.PHP','4.Perl','5.JavaScript')
My simple code is:
from tkinter import *
root = Tk()
values = ('1.Python','2.Ruby','3.PHP','4.Perl','5.JavaScript')
ru = Button(root,
text="Next",
)
ru.grid(column=0,row=0)
lab = Label(root,
text=values[0])
lab.grid(column=1,row=0)
ru2 = Button(root,
text="Previous"
)
ru2.grid(column=2,row=0)
root.mainloop()
I have two tkinter buttons "next" and "previous", the text value of the Label is directly taken from the tuple (text=value[0]), however I would want to know how to show the next string from the tuple when the next button is pressed, and how to change it to the previous values when the "previous" button is pressed. I know it can be done using for-loop but I cannot figure out how to implement that. I am new to python.
Use Button(..., command=callback) to assign function which will change text in label lab["text"] = "new text"
callback means function name without ()
You will have to use global inside function to inform function to assign current += 1 to external variable, not search local one.
import tkinter as tk
# --- functions ---
def set_next():
global current
if current < len(values)-1:
current += 1
lab["text"] = values[current]
def set_prev():
global current
if current > 0:
current -= 1
lab["text"] = values[current]
# --- main ---
values = ('1.Python','2.Ruby','3.PHP','4.Perl','5.JavaScript')
current = 0
root = tk.Tk()
ru = tk.Button(root, text="Next", command=set_next)
ru.grid(column=0, row=0)
lab = tk.Label(root, text=values[current])
lab.grid(column=1, row=0)
ru2 = tk.Button(root, text="Previous", command=set_prev)
ru2.grid(column=2, row=0)
root.mainloop()
BTW: if Next has to show first element after last one
def set_next():
global current
current = (current + 1) % len(values)
lab["text"] = values[current]
def set_prev():
global current
current = (current - 1) % len(values)
lab["text"] = values[current]

TKinter Change Label with "Next" Button

The program is meant to review a set of sentences one at a time. I want to show one and then when the "next" button is clicked, it shows the next input. Right now it blasts through them. How do I get it to stop? I have a feeling I'm missing something small.
So here's the code:
from Tkinter import *
import ttk
root = Tk()
def iterate(number):
return number + 1
inputs = open("inputs.txt").readlines
lines = inputs()
numlines = len(lines)
x=0
for tq in lines:
sentence = lines[x].strip('\n')
sen = StringVar()
sen.set(sentence)
x = iterate(x)
ttk.Label(textvariable = sen).grid(column=1, row=1, columnspan=99)
ttk.Button(text = "next", command = x).grid(column=99, row=5, pady=5)
root.update()
root.mainloop()
To change what is displayed in a label you can call the configure method, giving it any of the same arguments you give when you create it. So, you would create a single label, then call this method to modify what is displayed.
The basic logic looks like this:
def do_next():
s = get_next_string_to_display()
the_label.configure(text=s)
the_label = ttk.Label(...)
the_button = ttk.Button(..., command=do_next)
This is the code I ultimately used to solve the issue:
from Tkinter import *
import ttk
root = Tk()
root.title("This space intentionally left blank")
root.minsize(800,200)
mainframe = ttk.Frame(root)
mainframe.grid(column = 0, row = 0)
def nextInputs(*args):
sen.set(inputs())
inputs = open("inputs.txt").readline
sen = StringVar()
ttk.Label(mainframe, textvariable=sen).grid(column=1, row=1, columnspan=99)
Button = ttk.Button(mainframe, text = "next", command = nextInputs).grid(column=99, row=5, pady=5)
root.bind('<Return>', nextInputs)
root.mainloop()

Categories