Update dropdown based on selection of another dropdown in ipywidgets - python

I have a dropdown menu that shows soms posssible 'cycles'. These are actually .csv files containing some data. Then I have another dropdown that should show all the variables in this .csv file. So this second dropdown should update according to the file selected in the first dropdown. I found a similar
question and tried to implement this, but it did not work. The second dropdown remains empty. Note that I use pyspark to read the .csv files.
Cycles is a tuple containing all the .csv files in my working directory.
scW1 = widgets.Dropdown(description = 'Select file',options = cycles)
scW2 = widgets.Dropdown(description = 'Select variable')
def plotvar(sender):
df=sc.textFile(str(scW1.value)).map(lambda x: x.split(','))
header = tuple(df.first())
print(header)
with scW2.hold_trait_notifications():
scW2.options = header
display(scW1)
display(scW2)
What goes wrong?

Lol 4 years, but I've been looking for this...
from IPython.display import display
from ipywidgets import Dropdown
def dropdown_eventhandler(change):
determine(dropdown.value)
# print(change.new)
option_list = (1, 2)
dep_1 = (1, 1)
dep_2 = (2, 2)
def determine(x):
if x == 1:
dropdown_dep.options = dep_1
else:
dropdown_dep.options = dep_2
dropdown = Dropdown(description="Choose one:", options=option_list)
dropdown_dep = Dropdown(description="Choose one:")
dropdown.observe(dropdown_eventhandler, names='value')
display(dropdown, dropdown_dep)

Related

Why am I getting a type error from this function?

I am trying to create a drop down menu in tkinter that allows the user to select a machine, or row # from the excel sheet, and then all the data from that entire row is displayed in tkinter through the display_selected function. I keep getting this error.
This is my error:
TypeError: line_7_window.<locals>.display_selected() takes 0 positional arguments but 1 was given
This is my code:
def get_machine():
for row in sheet.iter_rows(min_row=2, max_col=1, max_row=60):
for cell in row:
if cell.value == inputmachine:
machineindex = cell
return machineindex.row
def get_machineattributes():
for col in sheet.iter_cols(min_row = (get_machine()), max_col = 15, max_row = (get_machine())):
for cell in col:
return (cell.value)
def display_selected():
data = Message(line_7, text=get_machineattributes())
data.pack()
data.place(x=650, y=30)
copy = Button(line_7, text="Copy to Clipboard", command=pyperclip.copy(line7_choice))
copy.pack()
copy.place(x=550, y=45)
return
inputmachine = StringVar(line_7)
inputmachine.set("Click to select a machine")
dropdown = OptionMenu(line_7, inputmachine, *lst, command=display_selected)
dropdown.pack()
dropdown.place(x=670, y=25)
I have tried everything and I cant figure out why this would not work.
Your callback function display_selected, specified when creating the option menu, will receive the actual option chosen from Tk, so you need that parameter when defining it, even if you do nothing with it.
In other words, use something like:
def display_selected(choice):
del choice # not used
# rest of function
As an aside, I suspect you may be better off with an option menu to select the item, and a separate button to act on that selection. That would allow you to confirm the selected item before performing any action, in case you inadvertently choose the wrong one.

Folium - add larger pop ups with data from XML file

I would like to create a table-like pop-up for my folium map but don't know how to do it (I'm a novice).
My data comes from an XML file that contains the gps coordinates, name, sales, etc. of stores.
Right now I can display the name of the stores in the pop-up, but I would also like to display the sales and other information below the name.
I reckon I should maybe use GeoJson but I don't know how to implement it in the code I already have (which contains clusterization) :
xml_data = 'Data Stores.xml'
tree = ElementTree.parse(xml_data)
counter = tree.find('counter')
name = counter.find('Name')
counter.find('Latitude').text
name = []
latitude = []
longitude = []
for c in tree.findall('counter'):
name.append(c.find('Name').text)
latitude.append(c.find('Latitude').text)
longitude.append(c.find('Longitude').text)
df_counters = pd.DataFrame(
{'Name' : name,
'Latitude' : latitude,
'Longitude' : longitude,
})
df_counters.head()
locations = df_counters[['Latitude', 'Longitude']]
locationlist = locations.values.tolist()
map3 = folium.Map(location=[31.1893,121.2781], tiles='CartoDB positron', zoom_start=6)
marker_cluster = folium.plugins.MarkerCluster().add_to(map3)
for point in range(0, len(locationlist)):
popup=folium.Popup(df_counters['Name'][point], max_width=300,min_width=300)
folium.Marker(locationlist[point],
popup=popup,
icon=folium.Icon(color='blue', icon_color='white',
icon='fa-shopping-bag', angle=0, prefix='fa')
).add_to(marker_cluster)
map3.save("WorldMap.html")`
Right now I have 4 other columns in my XML file besides 'Name' that have the information that I want to appear in the popup as well, kinda like this :
example popup
Thank you for your help
Edit :
I did some digging and changed my code a little bit by adding the folium.features.GeoJsonPopup instead of the simple folium.Popup that I had before :
for point in range(0, len(locationlist)):
popup=folium.features.GeoJsonPopup(
fields=[['Name'],['Opening']],
aliases=['Name','Opening'])
folium.Marker(locationlist[point],
popup=popup,
icon=folium.Icon(color='blue', icon_color='white',
icon='fa-shopping-bag', angle=0, prefix='fa')
).add_to(marker_cluster)
I added the 'Opening' data, however I don't know how to transfer it into the pop up along with the 'Name' since it comes from a panda DataFrame. Right now my popups are empty.
I have done something similar, steps were:
create an IFrame with the content you want to display (coded in HTML)
use this IFrame in a popup
connect this popup with your marker
htmlstr = ... # Here you can add your table, use HTML
# 1. iframe
iframe = folium.IFrame(htmlstr, # places your content in the iframe
width=200,
height=200 # adjust size to your needs
)
# 2. popup
fpop = folium.Popup(iframe)
# 3. marker
mrk = folium.Marker(location=latlng,
popup=fpop,
)
mrk.add_to( ... )

Python ttk combobox value update?

I use a GUI for some web automation with selenium.
I have several comboboxes (will do one example here)
This is my example code:
app = Tk()
def callback(*args): # should get the updated values in Combobox ?
global v_sv_league
v_sv_league = str(sv_league.get())
#List to be filled by scraper
li_leagues = []
#StringVar
sv_league = StringVar()
sv_league.trace("w", callback)
#Label
l_d_league = tk.Label(app,text='League:',bg='#1d1b29', fg='#f8f09d',font='Tahoma 10')
#Combobox
d_league = ttk.Combobox(app,textvariable=sv_league,values=li_leagues)
#Scrape
def scrape():
btn_tflist = wait.until(EC.element_to_be_clickable((By.XPATH,('/html/body/main/section/nav/button[3]'))))
btn_tflist.click()
btn_tf_filters = wait.until(EC.element_to_be_clickable((By.XPATH,'/html/body/main/section/section/div[2]/div/div/div[2]/div[2]')))
btn_tf_filters.click()
bol_scrape = True
if bol_scrape is True:
print('\n Start scraping... this might take a few minutes. Please wait and dont press anything until trade_buddy is done!\n')
li_leagues = []
print('Getting leagues...\n')
league_dropdown_menu = wait.until(EC.element_to_be_clickable((By.XPATH,('/html/body/main/section/section/div[2]/div/div[2]/div/div[1]/div[1]/div[7]/div'))))
league_dropdown_menu.click()
time.sleep(1)
# scrape all text
scrape_leagues = driver.find_elements_by_xpath("//li[#class='with-icon' and contains(text(), '')]")
for league in scrape_leagues:
export_league = league.text
export_league = str(export_league)
export_league = export_league.replace(',', '')
li_leagues.append(export_league)
app.mainloop()
So basically this is just a small part of my code but this is what I got for one of my combobox's.
You can see that I will call for def scrape at some point in my code to scrape data and to fill my list li_leagues.
However, my combobox is not refreshing the content and stays empty.
For OptionMenu I got it set up (with a it other code) but I cant get it working with combobox.
Any advice what I am missing here?
Thanks a slot!
Try using this line of code, after appending the list with values.
.....
export_league = export_league.replace(',', '')
li_leagues.append(export_league)
c_league.config(values=li_leagues)
config() method acts as a updater that just updates your widget, when called.
Hope it was of some help.
Cheers

How can I create a table in a DOCX file with Python?

I am trying to send selected values from radiobuttons into a .docx file
importing what I need, focus is on docx
import tkinter as tk
from docx import Document
main = tk.Tk()
these are my options that I need to place into a word document on the left of the table, they act as questions in a survey.
info = ["option 1", "option 2", "option 3", "option 4"
]
Here I am placing radiobuttons called Yes, No & N/A which are answers to the options on the left(list of info above) and also Label to represent options or in other words questions..
vars = []
for idx,i in enumerate(info):
var = tk.IntVar(value=0)
vars.append(var)
lblOption = tk.Label(main,text=i)
btnYes = tk.Radiobutton(main, text="Yes", variable=var, value=2)
btnNo = tk.Radiobutton(main, text="No", variable=var, value=1)
btnNa = tk.Radiobutton(main, text="N/A", variable=var,value=0)
lblOption.grid(column=0,row=idx)
btnYes.grid(column=1,row=idx)
btnNo.grid(column=2,row=idx)
btnNa.grid(column=3,row=idx)
Here is my function, creating a document and saving is the easy part. My issue is that I am muddled up creating a table that will have; Options on the left (from info) at the top are the headers (see RadioButtons yes, no, & N/a). And selected data, as an example, if for option 1 I have selected No, then save the data into a .docx file with the one been selected (See example bottom of page at Desired output).
def send():
document = Document()
section = document.sections[0]
#add table
table = document.add_table(1, 4)
#style table
table.style = 'Table Grid'
#table data retrived from Radiobuttons
items = vars.get()
#populate header row
heading_cells = table.rows[0].cells
heading_cells[0].text = "Options"
heading_cells[1].text = btnYes.cget("text")
heading_cells[2].text = btnNo.cget("text")
heading_cells[3].text = btnNa.cget("text")
for item in items:
cells = table.add_row().cells
cells[0].text = #Options
cells[1].text = #Yes values
cells[2].text = #No values
cells[3].text = #N/A values
#save doc
document.save("test.docx")
#button to send data to docx file
btn = tk.Button(main, text="Send to File", command= send)
btn.grid()
main.mainloop()
this is what it opens up:
Here is the desired output:
Number 1 represents selected items from the tkinter application. But will figure out how to change it to a tick box.
I am kinda confused where I am at, I am new using docx.. been trying to read the documentation.. and this is where I digged my self a hole into.
In your current code, vars is a list of IntVars. You want to get each value individually instead of vars.get(). Also when writing to docx file, you need both info and values of radiobuttons, to track them both you can use an index.
With minimal changes to your code, you can use something like this.
def send():
...
...
heading_cells[3].text = btnNa.cget("text")
for idx, item in enumerate(vars):
cells = table.add_row().cells
cells[0].text = info[idx] # gets the option name
val = item.get() #radiobutton value
if val == 2: # checks if yes
cells[1].text = "1"
elif val == 1: # checks if no
cells[2].text = "1"
elif val == 0: # checks if N/A
cells[3].text = "1"
#save doc
document.save("test.docx")
or you can use a dictionary to map radiobuttons to cells.
valuesCells = {0: 3, 1: 2, 2: 1} # value of radiobutton: cell to write
# hard to read what's going on though
for idx, item in enumerate(vars):
cells = table.add_row().cells
cells[0].text = info[idx] # gets the option name
val = item.get()
cells[valuesCells[val]].text = "1"
#save doc
document.save("test.docx")

Display and update text with Bokeh: settings glyph on update not working

I am trying to write a web app that displays graphs with Bokeh and also displays formatted text retrieved from an API. The display dynamically changes with the content of the graph when the user clicks a button. Is there a standard way to format and present text, and then update it, with Bokeh?
I thought I could do this with text glyphs, but so far I am failing. Here's what I'm trying to do for the update action:
def update_graph(attrname, old, new):
USER_ID = new
use_df = get_user_df(new, cur, date_from, date_to)
plot1.title = get_api_output(new, INSIGHT_DATE)
textplot.text(3, 3, text=["hellllllo"], text_color="firebrick", text_align="center", text_font_size="20pt")
source1.data['x'] = use_df[use_df['type'] == 0]['date'].values
source1.data['y'] = use_df[use_df['type'] == 0]['value'].values
This mostly works fine the way it is. I grab some data from a remote DB with get_user_df and update source1, which works appropriately. Similarly the title gets updated as desired.
However no text glyph appears on textplot and no error appears in the console. What's going on and how can I dynamically adjust text glyphs on a plot?
Also here is the code I use to set up the plots in case that is relevant:
#plot utilities
def mtext(p, x, y, text):
p.text(x, y, text=[text],
text_color="firebrick", text_align="center", text_font_size="10pt")
#PLOTS
textplot = Figure(toolbar_location = None, title = 'API text', title_text_font_size='8pt')
mtext(textplot, randint(2, 5), randint(2, 5), 'annotation')
plot1 = Figure(toolbar_location = None, title = 'Distance (k)', title_text_font_size='8pt')
source1 = ColumnDataSource(data = dict(x = use_df[use_df['type'] == 0]['date'].values, y = use_df[use_df['type'] == 0]['value'].values))
plot1.circle('x', 'y', line_color=None, source = source1, color = 'pink', size = 20)

Categories