Python: Save radio Button tkinter values in an Excel file - python

I'm trying to create a small interface with Tkinter with 4 radio buttons and each time I click on one of the buttons it will print the value of the button, I've managed to do that!
However, I would like the printed value to be saved in an Excel file for example each time I click on one of the buttons in my tkinter window.
Below is the code I used and the result I got:
from tkinter import *
import tkinter as tk
master = Tk()
master.geometry("175x175")
# Tkinter string variable
# able to store any string value
v = IntVar(master, "0") #0 pour qu'aucun des boutons soit sélectioné par défaut
# Dictionary to create multiple buttons
values = {"classe 1" : "1",
"classe 2" : "2",
"classe 3" : "3",
"classe 4" : "4"}
def affiche ():
val = v.get()
print(val)
data = [
['class1', val],
]
labelValue = tk.Label(master,
text="""Choose your class affectation:""",
justify = tk.LEFT,
padx = 20).pack()
for (text, value) in values.items():
Radiobutton(master, text = text, variable = v, command = affiche,
value = value).pack(side =TOP, ipady = 5)
# Infinite loop can be terminated by
# keyboard or mouse interrupt
# or by any predefined function (destroy())
mainloop()
On the right of the capture below are the values I would like to save in an excel file each time I click.
I got them by clicking respectively on class1, class2, class3 and class4
enter image description here
I am a beginner, any help is appreciated!
Thank you very much.

I just completed the previous program
def affiche ():
val = v.get()
print(val)
workbook = xlsxwriter.Workbook('Mon fichier.xlsx')
worksheet = workbook.add_worksheet("My sheet")
data = [
['class1', val],
['class2', val],
['class3', val],
['class4', val],
]
caption = 'My data.'
# Set the columns widths.
worksheet.set_column('B:G', 12)
# Write the caption.
worksheet.write('B1', caption)
# Add a table to the worksheet.
worksheet.add_table('B4:L4', {'header_row': 0})
# Table data can also be written separately, as an array or individual cells.
worksheet.write_row('B4', data[0])
worksheet.write_row('B5', data[1])
worksheet.write_row('B6', data[2])
worksheet.write_row('B7', data[3])
workbook.close()

Related

How can I display the contents of a variable that uses .sum() in a label using tkinter

I'm creating a counter to count how many empty cells there are when a user uploads a CSV file. I am also using treeview to display the contents of the CSV. The print("There are", emptyCells.sum(), "empty cells") works and prints the number to the console but I want to display this in a label so the user can view this in the GUI. It is not displaying anything but a "row" is being added to the application after a file has been uploaded where the label should be as everything moves down but no contents are being inserted into the label.
emptyCells = (df[df.columns] == " ").sum()
# print("There are", emptyCells.sum(), "empty cells")
tree.pack(side=BOTTOM, pady=50)
messagebox.showinfo("Success", "File Uploaded Successfully")
stringVariable = StringVar()
printVariable = ("There are", emptyCells.sum(), "empty cells")
#print(printVariable)
stringVariable.set(printVariable)
lbl = Label(windowFrame, textvariable=stringVariable, font=25)
lbl.pack()
According to your question you want to update your tkinter label by a button click. You would do this with something like this:
from tkinter import *
from tkinter import messagebox
root = Tk(className="button_click_label")
root.geometry("200x200")
messagebox.showinfo("Success","Test")
emptyCells = (df[df.columns] == " ").sum()
l1 = Label(root, text="Emptycells?")
def clickevent():
txt = "there are", emptyCells
l1.config(text=txt)
b1 = Button(root, text="clickhere", command=clickevent).pack()
l1.pack()
root.mainloop()
It is not tested with the pandas library but should work for you!
The problem with the tkinter label is not happening when I try to reproduce the problem, the label shows. The cause must be somewhere else in the code.
I've not got pandas installed so I've summed a list instead. This shows a GUI with two labels when I run it.
import tkinter as tk
emptyCells = [ 1, 1, 1, 1, 1, 1, 1 ] # keep it simple.
windowFrame = tk.Tk()
old = tk.StringVar()
stringVariable = tk.StringVar()
old_print = ("There are", sum(emptyCells), "empty cells") # Returns a tuple
printVariable = "There are {} empty cells".format( sum(emptyCells) ) # Returns a string.
old.set( old_print )
stringVariable.set(printVariable)
lbl_old = tk.Label( windowFrame, textvariable = old )
lbl_old.pack()
lbl = tk.Label(windowFrame, textvariable=stringVariable, font=25)
lbl.pack()
windowFrame.mainloop()
Does this work when you run it? Does it help identify where the problem is in the code which doesn't show the labels?
Don't you have the sum you need already in the emptyCells variable? Why do you need to use the .sum() function again in the print statement?
printVariable = f"There are {emptyCells} empty cells"

How to change a list depending on tkinter checkbutton

I have been trying to use tkinter CheckButton widget to edit items in a list - each item of the list is a new checkbutton. I want a save method to save the data to a text file, and a load method to load the info from the text file and mark the checkbutton boxes depending on the items in the list.
Here is my code so far, but the list doesn't seem to change when I check the buttons and update the list/file
Here is my code, I need to know why the list isn't updating when I check the boxes:
import tkinter.messagebox as box
modulesMain = Tk()
moduleChecks = []
def SaveChanges():
# Clear the text file
modules = open("modules.txt", "w") #Write mode to overwrite the whole file
modules.write("") # Put in blank text
modules.close()
modules = open("modules.txt", "a") # Append mode to append the file
for item in moduleChecks:
modules.write(item + "\n")
print(moduleChecks)
appButton = Checkbutton(modulesMain, text = "Test", variable = moduleChecks[0]).grid()
searchButton = Checkbutton(modulesMain, text = "Test", variable = moduleChecks[1]).grid()
Save = Button(modulesMain, text = "Save Changes", command = SaveChanges).grid()
The variable for each of your checkboxes needs to be an IntVar. Your moduleCheck list is currently un-initialised so when you try to access the elements inside it, you'll get an error.
In the below code (modified from yours), I've initialised the moduleCheck to contain two IntVars.
When you press the save button, it will print to the console the current state of the check boxes.
import tkinter as tk
modulesMain = tk.Tk()
moduleChecks = [tk.IntVar() for i in range(2)]
def SaveChanges():
for idx,item in enumerate(moduleChecks):
print(f"{idx} = {item.get()}")
appCheck = tk.Checkbutton(modulesMain, text = "App", variable = moduleChecks[0])
appCheck.grid()
searchCheck = tk.Checkbutton(modulesMain, text = "Check", variable = moduleChecks[1])
searchCheck.grid()
saveButton = tk.Button(modulesMain, text = "Save Changes", command = SaveChanges)
saveButton.grid()
modulesMain.mainloop()
Here is a basic solution.
import tkinter as tk
root = tk.Tk()
#list of options. doubles as checkbox label text
#appending to this list is all that is necessary to create more options
opts = ['App', 'Search']
#create an StringVar for every option
#this way there doesn't have to be type conversions for reading/writing files
vars = [tk.StringVar(value='0') for _ in opts]
#create checkboxes for every option
for opt, var in zip(opts, vars):
tk.Checkbutton(root, text=opt, variable=var, onvalue='1', offvalue='0').grid(sticky='w')
#write the checkbox values to file
def save_options_state():
with open("modules.txt", "w") as file:
file.write(''.join([v.get() for v in vars]))
#set checkbox values from file
def load_options_state():
with open("modules.txt", "r") as file:
for n, var in zip(list(file.read().strip()), vars):
var.set(n)
#save/load buttons
tk.Button(root, text="save", command=save_options_state).grid()
tk.Button(root, text="load", command=load_options_state).grid(row=2, column=1)
root.mainloop()
Here's a runnable example which I think shows how to do everything you've asked about. It assumes the modules.txt file contains data in the following format, where each line consists of a module's name and whether it's checked or not.
Mod1,0
Mod2,0
Mod3,0
The data in the file is used to create a list of Checkbuttons — one for each module — and initially sets to its current status as indicated in the file.
Here's the sample code:
from tkinter import *
import tkinter.messagebox as box
dataFilename = "modules.txt"
moduleChecks = []
def ReadModules():
with open(dataFilename, "r") as file:
for line in (line.strip() for line in file):
moduleName, moduleState = line.split(',')
moduleChecks.append((moduleName, int(moduleState)))
print('read:', moduleChecks)
def SaveChanges():
print('writing:', moduleChecks)
with open(dataFilename, "w") as file:
for checkButton in moduleCheckbuttons:
moduleName = checkButton.cget('text')
moduleState = checkButton.var.get()
file.write(','.join((moduleName, str(moduleState))) + '\n')
ReadModules()
modulesMain = Tk()
moduleCheckbuttons = []
# Create a Checkbutton for each module based on moduleChecks values.
for moduleName, moduleState in moduleChecks:
intVar = IntVar(value=moduleState)
checkButton = Checkbutton(modulesMain, text=moduleName, variable=intVar)
checkButton.var = intVar # Attach reference to variable.
checkButton.grid()
moduleCheckbuttons.append(checkButton)
saveButton = Button(modulesMain, text="Save Changes", command=SaveChanges)
saveButton.grid()
modulesMain.mainloop()

Python tkinter how to use what is typed into an entry widget

How do I use what is entered into a Tkinter entry widget in the rest of the program?
I have this for the entry:
n = StringVar()
Entry(search1, textvariable=n).pack()
label = n.get()
with open('data.txt') as json_file:
data = json.load(json_file)
for p in data:
recipe = p['recipe']
recipeNames= recipe['label']
if recipeNames == label:
recipeName = label
ingredients = []
for j in recipe['ingredients']:
ingredients.append(j['text'])
Button(search1, text="Enter", command=partial(addrecipe, recipeName, calendarID, ingredients, service)).pack()
When I try to use the variable it has nothing in it and comes back with an error. How do I assign a variable to what is in the entry widget?

Tkinter labels not returning the proper value

Using python 2.7 and Tkinter.
I am creating four lables in a loop and binding them to . I want the label to return
the name in the label's text.
The problem is that no matter which label I press it returns the name in the last label.
I found this question Python Tkinter: Bind function with labels in for loop with exactly my problem but the solution given does not work for me even if I copied the code exactly.
Please anyone? here is my original code:
# labelbind.py
from Tkinter import *
root = Tk()
root.title('Label choices')
root.geometry('1160x900+650+50')
root.option_readfile('setstyle2.txt')
def lblpress(x):
print 'Label pressed', x
names = ['AMEX', 'CIBC', 'VISA', 'BMO']
col = 150
row = 45
num = 1
for name in names:
bobo = 'lbl' + str(num)
print bobo, name
bobo = Label(root, text = name)
bobo.bind('<ButtonRelease-1>', lambda x = name : lblpress(name))
bobo.place(x = col, y = row)
row += 40
num += 1
root.mainloop()
You don't need to pass anything to the callback. The event object that is given to the callback contains a reference to the widget, and from the widget you can get the text.
For example:
import Tkinter as tk
def lblpress(event):
print 'Label pressed:', event.widget.cget("text")
root = tk.Tk()
names = ['AMEX', 'CIBC', 'VISA', 'BMO']
for name in names:
label = tk.Label(root, text=name)
label.bind("<ButtonRelease-1>", lblpress)
label.pack(side="top")
root.mainloop()

Is it possible to display hyperlinks in a Tkinter message widget?

I am creating a news feed program that uses the Feedparser module to read the Yahoo! RSS API, write key data to a text file, and then display the data organised in a Tkinter GUI.
I was enquiring if it is possible to have clickable hyperlinks in a text file/Tkinter message widget.
My current thinking is that you could write code that runs in the following fashion:
If item in the text file includes 'http', make it a hyperlink.
If anyone knows of a Pythonic way to achieve this, or knows if it is not in fact possible, please contribute.
Thank you for your time, here is my code:
def news_feed(event):
''' This function creates a new window within the main window, passes an event(left mouse click), and creates a text heading'''
root = Toplevel(window)
# Create a text heading and define its placement within the grid
menu_heading = Label(root, text = 'News feed', font = 'bold')
menu_heading.grid(row = 0, column = 0, columnspan = 3, pady = 4)
# Create a variable of the selected radio button
button_choice = IntVar()
def selection():
''' This function gets the activated radio button and calls its corresponding function.'''
# Get the value of the activated radio button, and call its corresponding function
news_choice = button_choice.get()
# If the user's choice is industry news, ask them which feed they would like (E.g. Stock market),
if news_choice == 0:
# grab the corresponding url segment to the user's feed choice from the dictionary,
news_choice_url = news_areas[news_feed]
# set the url variable using by inserting this segment into the API url,
rss_url = feedparser.parse('https://au.finance.yahoo.com/news/' + news_choice_url + '/?format=rss')
# and call the feed parsing function.
parse_feed()
# If the user's choice is the second button, call the company news function
elif news_choice == 1:
company_news()
def read_news_file(news_feed_message):
'''This function opens the companyNews text file and reads its contents, line by line'''
with open('C:\\Users\\nicks_000\\PycharmProjects\\untitled\\SAT\\GUI\\Text Files\\companyNews.txt', mode='r') as inFile:
news_data_read = inFile.read()
print('\n')
news_feed_message.configure(text = news_data_read)
def parse_feed(news_feed_message, rss_url):
''' This function parses the Yahoo! RSS API for data of the latest five articles, and writes it to the company news text file'''
# Define the RSS feed to parse from, as the url passed in of the company the user chose
feed = feedparser.parse(rss_url)
try:
# Define the file to write the news data to the company news text file
with open('C:\\Users\\nicks_000\\PycharmProjects\\untitled\\SAT\\GUI\\Text Files\\companyNews.txt', mode='w') as outFile:
# Create a list to store the news data parsed from the Yahoo! RSS
news_data_write = []
# Initialise a count
count = 0
# For the number of articles to append to the file, append the article's title, link, and published date to the news_elements list
for count in range(10):
news_data_write.append(feed['entries'][count].title)
news_data_write.append(feed['entries'][count].published)
article_link = (feed['entries'][count].link)
article_link = article_link.split('*')[1]
news_data_write.append(article_link)
# Add one to the count, so that the next article is parsed
count+=1
# For each item in the news_elements list, convert it to a string and write it to the company news text file
for item in news_data_write:
item = str(item)
outFile.write(item+'\n')
# For each article, write a new line to the company news text file, so that each article's data is on its own line
outFile.write('\n')
# Clear the news_elements list so that data is not written to the file more than once
del(news_data_write[:])
finally:
outFile.close()
read_news_file(news_feed_message)
def industry_news():
''' This function creates a new window within the main window, and displays industry news'''
industry_window = Toplevel(root)
Label(industry_window, text = 'Industry news').grid()
def company_news():
''' This function creates a new window within the main window, and displays company news'''
company_window = Toplevel(root)
company_label = Label(company_window, text = 'Company news')
company_label.grid(row = 0, column = 0, columnspan = 6)
def company_news_handling(company_ticker):
''' This function gets the input from the entry widget (stock ticker) to be graphed.'''
# set the url variable by inserting the stock ticker into the API url,
rss_url = ('http://finance.yahoo.com/rss/headline?s={0}'.format(company_ticker))
# and call the feed parsing function.
parse_feed(news_feed_message, rss_url)
# Create the entry widget where the user enters a stock ticker, and define its location within the grid
company_ticker_entry = Entry(company_window)
company_ticker_entry.grid(row = 1, column = 0, columnspan = 6, padx = 10)
def entry_handling():
'''This function validates the input of the entry box, and if there is nothing entered, an error is outputted until a value is'''
# Create a variable that equals the input from the entry widget
company_ticker = company_ticker_entry.get()
# Convert the input into a string
company_ticker = str(company_ticker)
if company_ticker == '':
news_feed_message.configure(text = 'Please input a stock ticker in the entry box.')
else:
company_news_handling(company_ticker)
# Create the button that the user presses when they wish to graph the data of the stock ticker they inputted in the entry widget
graph_button = Button(company_window, text = 'SHOW', command = entry_handling, width = 10).grid(row = 2, column = 0, columnspan = 6)
news_feed_message = Message(company_window, text='', width=500, borderwidth=5, justify=LEFT, relief=RAISED)
news_feed_message.grid(row=3, column=0, columnspan=6)
Most uses of hyperlinks in a tkinter application i have seen involved using the webbrowser and attaching events to your tkinter object to trigger callbacks, but there may be simpler ways, but heres what i mean :
from tkinter import *
import webbrowser
def callback(event):
webbrowser.open_new(r"http://www.google.com")
root = Tk()
link = Label(root, text="Google Hyperlink", fg="blue", cursor="hand2")
link.pack()
link.bind("<Button-1>", callback)
root.mainloop()
From this source
You could do as you said and read from a text file, and if the line contains "http" create a new label, and event, attaching the hyper link from the file to the event.
import re
with open(fname) as f:
content = f.readlines()
urls = re.findall('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_#.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', content)
Access the url's after this and generate your label's or whatever widget you attach the url's too and you can then have all of them open the web page when clicked.
Hope this helps in some way, let me know if you need more help :)
I think it is easy to create hyperlink in tkinter using following link and its easy for modifying as per your requirement
Updated Hyperlink in tkinter
hope this works for you.
regards Midhun
(Answer taken from effbot)
Support module for Text hyperlinks (File: tkHyperlinkManager.py)
from Tkinter import *
class HyperlinkManager:
def __init__(self, text):
self.text = text
self.text.tag_config("hyper", foreground="blue", underline=1)
self.text.tag_bind("hyper", "<Enter>", self._enter)
self.text.tag_bind("hyper", "<Leave>", self._leave)
self.text.tag_bind("hyper", "<Button-1>", self._click)
self.reset()
def reset(self):
self.links = {}
def add(self, action):
# add an action to the manager. returns tags to use in
# associated text widget
tag = "hyper-%d" % len(self.links)
self.links[tag] = action
return "hyper", tag
def _enter(self, event):
self.text.config(cursor="hand2")
def _leave(self, event):
self.text.config(cursor="")
def _click(self, event):
for tag in self.text.tag_names(CURRENT):
if tag[:6] == "hyper-":
self.links[tag]()
return
And here’s an example:
# File: hyperlink-1.py
import tkHyperlinkManager
from Tkinter import *
root = Tk()
root.title("hyperlink-1")
text = Text(root)
text.pack()
hyperlink = tkHyperlinkManager.HyperlinkManager(text)
def click1():
print "click 1"
text.insert(INSERT, "this is a ")
text.insert(INSERT, "link", hyperlink.add(click1))
text.insert(INSERT, "\n\n")
def click2():
print "click 2"
text.insert(INSERT, "this is another ")
text.insert(INSERT, "link", hyperlink.add(click2))
text.insert(INSERT, "\n\n")
mainloop()

Categories

Resources