Python 3 tkinter treeview get NAME of selected item - python-3.x

So basically I have this tree:
And I want to have the name of the item selected back by pressing the "aggiungi" button.
For example when I select Pomodori and then press the button I want "Pomodori" back as string, If I select Frutta I want "Frutta" and so on...
I tried with get.children and then tree.set() but I cant get that to work.
How do I do that?
from tkinter import *
from tkinter import ttk
_root = Tk()
_root.resizable(width=FALSE, height=FALSE)
_F_shopItems = Frame(_root)
_F_shopItems.pack(side="left")
_F_treeview = Frame(_root)
_F_treeview.pack(side="left")
_F_bottom = Frame(_root)
_F_bottom.pack(side="bottom")
# ------------------------
# Treeview
_T_listaProd = ttk.Treeview(_F_treeview, height=10)
_T_listaProd.column("#0", width=165)
_T_listaProd.heading("#0", text="Prodotti")
_T_listaProd.config(columns="Prezzi")
_T_listaProd.column("Prezzi", width=75, anchor="center")
_T_listaProd.heading("Prezzi", text="Prezzi (€/Kg)")
_T_listaProd.grid(row=0, column=0)
# Categorie di prodotti
_T_listaProd.insert('', '0', 'Verdura', text='Verdura')
_T_listaProd.insert('', '1', 'Frutta', text='Frutta')
_T_listaProd.insert('', '2', 'Carne', text='Carne')
_T_listaProd.insert('', '3', 'Dolci', text='Dolci')
# Verdura
_T_listaProd.insert('Verdura', 'end', 'V1', text='Insalata Gentile')
_T_listaProd.set("V1", "Prezzi", "0,98")
_T_listaProd.insert('Verdura', 'end', 'V2', text='Cipolla Bianca')
_T_listaProd.set("V2", "Prezzi", "0,98")
_T_listaProd.insert('Verdura', 'end', 'V3', text='Radicchio')
_T_listaProd.set("V3", "Prezzi", "0,98")
_T_listaProd.insert('Verdura', 'end', 'V4', text='Pomodori')
_T_listaProd.set("V4", "Prezzi", "0,98")
_T_listaProd.insert('Verdura', 'end', 'V5', text='Peperoni')
_T_listaProd.set("V5", "Prezzi", "0,98")
# Frutta
_T_listaProd.insert('Frutta', 'end', 'F1', text='Mele rosse')
_T_listaProd.set("F1", "Prezzi", "0,98")
_T_listaProd.insert('Frutta', 'end', 'F2', text='Ciliege')
_T_listaProd.set("F2", "Prezzi", "0,98")
# Dolci
_T_listaProd.insert('Dolci', 'end', 'D1', text='Crostata (Marmellata)')
_T_listaProd.set("D1", "Prezzi", "0,98")
_T_listaProd.insert('Dolci', 'end', 'D2', text='Nutella')
_T_listaProd.set("D2", "Prezzi", "0,98")
# Carne
_T_listaProd.insert('Carne', 'end', 'C1', text='Braciola di Maiale')
_T_listaProd.set("C1", "Prezzi", "0,98")
_T_listaProd.insert('Carne', 'end', 'C2', text='Pancetta')
_T_listaProd.set("C2", "Prezzi", "0,98")
_T_listaProd.insert('Carne', 'end', 'C3', text='Salame')
_T_listaProd.set("C3", "Prezzi", "0,98")
# Scrollbar
_S_listaProd = Scrollbar(_F_treeview, orient=VERTICAL, command=_T_listaProd.yview)
_S_listaProd.grid(row=0, column=1, sticky="nswe")
_T_listaProd.config(yscrollcommand=_S_listaProd.set)
# ------------------------
_T_listaProd.bind('<<TreeviewSelect>>', #To do#)
_B_addItem = Button(_F_bottom, text="aggiungi", command = #To do#)
_B_addItem.pack(side="bottom")
_main.mainloop()

Virtual event <<TreeviewSelect>> and method ttk.Treeview.selection might be what you need,
import tkinter as tk
from tkinter import ttk
class Frame(ttk.Frame):
def __init__(self, *args, **kw):
ttk.Frame.__init__(self, *args, **kw)
self.tree = ttk.Treeview(self)
self.tree.pack()
for i in range(10):
self.tree.insert("", tk.END, text="item %s" % i)
self.tree.bind('<<TreeviewSelect>>', self.on_select)
self.button = ttk.Button(self, text="test", command=self.print_selected)
self.button.pack()
self.selected = []
def on_select(self, event):
self.selected = event.widget.selection()
def print_selected(self):
for idx in self.selected:
print(self.tree.item(idx)['text'])
if __name__ == "__main__":
root = tk.Tk()
frame = Frame(root)
frame.pack()
root.mainloop()

Related

Save chart as image from dash at start

I have some charts generated through Dash and I would like these charts to be saved at Dash server start.
app.layout = html.Div(
children=[
dcc.Graph(
id='serious-chart',
style={
"width": '1000px',
'height': '500px',
}
),
],style={'position':'absolute',
'width':'160vh',
'height':'55vh',
'top': '142%',
'left': '50%',
'border': '1px solid black',
'border-radius':'10px',
"transform": "translate(-50%, -50%)",
}
)
#app.callback(
Output(component_id='serious-chart',component_property='figure'),
Input(component_id='input-bar',component_property='value'),
)
def returnCharts(value):
""" some code here """
if __name__ == '__main__':
app.run_server(debug=True)
Need some code to save Figure 'serious-chart' as jpeg or Png.

How to pass the dataframe along list in dash framework?

I'm trying to pass the data frame and selected property of a dropdown to the different calling function in dash. I'm able to pass selected value but i don't get data frame. Here is my code.
"""Visualization graph"""
import os
from flask import Flask
import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px
import pandas as pd
DIRECTORY_PATH = 'C:/Users/fortu/Desktop/Zuhair/'
directories = [
d for d in (os.path.join(DIRECTORY_PATH, directories) for directories in
os.listdir(DIRECTORY_PATH))
if os.path.isdir(d)
]
external_stylesheets = [
'https://js.api.here.com/v3/3.1/mapsjs-ui.css'
]
# Normally, Dash creates its own Flask server internally. By creating our own,
# we can create a route for downloading files directly:
server = Flask(__name__)
app = dash.Dash(__name__,
external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div(
[
dbc.Row(dbc.Col(
html.Div("Ground truth visualization",
style={'textAlign': 'center',
'color': 'red', 'fontSize': '40px'}),
md=12)),
dbc.Row(
dbc.Col(
html.Div([
dbc.Row([
dbc.Col(html.Div(dbc.Row(dcc.Dropdown(
id='selected-dir',
options=[{'label': i, 'value': i}
for i in directories],
placeholder="Select the directory"),
style={
'marginLeft': '25px',
'display': 'inline-block',
'width': '90%'
}
)), width=2),
dbc.Col(children=[
html.Div(dbc.Row(dcc.Dropdown(
id='selected-csv-fields',
placeholder="Select the field"),
style={
'display': 'inline-block',
'width': '90%'
}
)),
html.Div(dbc.Row(id='intermediate-value'), style={'display': 'none'})
], width=2),
]),
dbc.Row([
dbc.Col(html.Div([
dbc.Row(
[dbc.Col(html.Div(
dcc.Graph(id='line-graph'),
className='bg-dark badge-dark'))]),
dbc.Row([dbc.Col(html.Div(
dcc.Graph(id='stack-graph'),
className='bg-warning'))],
className="row mt-3")]), width=5)
], className="row mt-3")]))
)
]
)
#app.callback(
[Output("selected-csv-fields", "options"),
Output("intermediate-value", "data")],
[Input("selected-dir", "value")]
)
def get_all_csv(selector):
"""Get all the csv from the folder"""
if selector is not None:
csv_files = list(filter(lambda x: '.csv' in x, os.listdir(selector)))
_DF = pd.concat([pd.read_csv(os.path.join(selector, f))
for f in csv_files])
demo = [{'label': i, 'value': i} for i in _DF]
return demo, _DF
return []
#app.callback(
Output("line-graph", "figure"),
Output("stack-graph", "figure"),
[Input("selected-csv-fields", "value"), Input("intermediate-value", "data")]
)
def update_graph(selector, done):
"""display the graph based on selected value."""
if selector is not None:
fig = px.line(done, x="Time", y=selector)
stack = px.histogram(done, x="Time", y=selector, marginal="box",
hover_data=done)
return fig, stack
return {}, {}
if __name__ == "__main__":
app.run_server(debug=True)
When I remove the Output("intermediate-value", "data")] from get_all_csv() and Input("intermediate-value", "data") from update_graph(a, b) respectively it works fine. but when try to pass this parameters it gives me error
ERROR :
Callback error updating selected-csv-fields.options, intermediate-value.data

Create a modal when clicking on barchart with dash plotly

I have a bar chart and I would like to create a Modal when I click on them. Do you know how I can handle that? I tried something but nothing appears.
I knew how to do it with a datatable. But here I have a bar chart, I added a Modal object at the end of the design but I can't make it appear despite.
Here is a minimal reproducible example:
import dash
import dash_core_components as dcc
import dash_bootstrap_components as dbc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
from dash.dependencies import Input, Output
df = pd.read_excel("https://github.com/chris1610/pbpython/blob/master/data/salesfunnel.xlsx?raw=True")
pv = pd.pivot_table(df, index=['Name'], columns=["Status"], values=['Quantity'], aggfunc=sum, fill_value=0)
trace1 = go.Bar(x=pv.index, y=pv[('Quantity', 'declined')], name='Declined')
trace2 = go.Bar(x=pv.index, y=pv[('Quantity', 'pending')], name='Pending')
trace3 = go.Bar(x=pv.index, y=pv[('Quantity', 'presented')], name='Presented')
trace4 = go.Bar(x=pv.index, y=pv[('Quantity', 'won')], name='Won')
app = dash.Dash()
app.layout = html.Div(children=[
html.H1(children='Sales Funnel Report'),
html.Div(children='''National Sales Funnel Report.'''),
dcc.Graph(
id='graph',
figure={
'data': [trace1, trace2, trace3, trace4],
'layout':
go.Layout(title='Order Status by Customer', barmode='stack')
}),
dbc.Modal(
[
dbc.ModalHeader("Header"),
dbc.ModalBody("This is the content of the modal"),
dbc.ModalFooter(
dbc.Button("Close", id="close", className="ml-auto")
),
],
size="xl",
id="modal",
)
])
#app.callback(
Output('modal', 'children'),
[Input('graph', 'clickData')])
def display_click_data(clickData):
print("clickData: ", clickData)
return [
dbc.ModalHeader("Test"),
dbc.ModalBody(
html.Div([
html.Div([
html.H6('Sales', style={'textAlign': 'center', 'padding': 10}),
html.P("Bitch", id="sales_stocks", style={'textAlign': 'center', 'padding': 10})
], className='pretty_container four columns'),
html.Div([
html.H5('Current ratio', style={'textAlign': 'center', 'padding': 10})
], className='pretty_container seven columns')
])),
dbc.ModalFooter(dbc.Button("Close", id="close"))
]
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
app.run_server(debug=True)
I encountered a similar question, but conceptually the same: click on something in a plotly/dash-object and then display a modal. Researching the issue, I also found this post on the plotly forum, which encounters very similar problems. The proposed solution there gave me the idea on how to solve.
There are 2 issues at hand if I copy your code.
its missing the link to the bootstrap "external stylesheet" which can be easily added in your sample above, replacing app = dash.Dash() with app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])
the call back now only alters the modal's children. However, to be displayed, it's attribute, open should be set to True. When the button, with id=close is pressed, the open be altered to False.
I worked your code snipped out into something working. Hope this helps you out as well!
import dash_core_components as dcc
import dash_bootstrap_components as dbc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
# added State to be used in callbacks
from dash.dependencies import Input, Output, State
# using #type: ignore to suppress warnings in my editor (vs code).
df = pd.read_excel("https://github.com/chris1610/pbpython/blob/master/data/salesfunnel.xlsx?raw=True")
pv = pd.pivot_table(df, index=['Name'], columns=["Status"], values=['Quantity'], aggfunc=sum, fill_value=0)#type: ignore
trace1 = go.Bar(x=pv.index, y=pv[('Quantity', 'declined')], name='Declined') #type: ignore
trace2 = go.Bar(x=pv.index, y=pv[('Quantity', 'pending')], name='Pending')#type: ignore
trace3 = go.Bar(x=pv.index, y=pv[('Quantity', 'presented')], name='Presented')#type: ignore
trace4 = go.Bar(x=pv.index, y=pv[('Quantity', 'won')], name='Won')#type: ignore
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div(children=[
html.H1(children='Sales Funnel Report'),
html.Div(children='''National Sales Funnel Report.'''),
dcc.Graph(
id='graph',
figure={
'data': [trace1, trace2, trace3, trace4],
'layout':
go.Layout(title='Order Status by Customer', barmode='stack')#type: ignore
}),
dbc.Button("toggle", id="open"),
dbc.Modal(
[
dbc.ModalHeader("Header",id = 'modalheader'),
dbc.ModalBody("This is the content of the modal"),
dbc.ModalFooter(
dbc.Button("Close", id="close", className="ml-auto")
),
],
size="xl",
id="modal",
)
])
#app.callback([Output("modal", "children"),
Output("modal", "is_open")],
[Input("graph", "clickData"),
Input("close", "n_clicks")],
[State("modal", "is_open"),
State("modal", "children")])
def set_content(value,clicked,is_open,children):
ctx = dash.callback_context
if ctx.triggered[0]['prop_id'] == 'close.n_clicks':
# you pressed the closed button, keeping the modal children as is, and
# close the model itself.
return children, False
elif ctx.triggered[0]['prop_id'] == 'graph.clickData':
# you clicked in the graph, returning the modal children and opening it
return [dbc.ModalHeader("Test"),
dbc.ModalBody(
html.Div([
html.Div([
html.H6('Sales', style={'textAlign': 'center', 'padding': 10}),
html.P("Bitch", id="sales_stocks", style={'textAlign': 'center', 'padding': 10})
], className='pretty_container four columns'),
html.Div([
html.H5('Current ratio', style={'textAlign': 'center', 'padding': 10}),
html.P(str(value),style = {'fontFamily':'monospace'})
], className='pretty_container seven columns')
])),
dbc.ModalFooter(dbc.Button("Close", id="close"))
], True
else:
raise dash.exceptions.PreventUpdate
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
app.run_server(debug=True)

Why is dashboard created using Dash not working?

I'm trying to create a Dashboard using Dash, a python package. It is either taking too much of time to execute or throws an error saying "error in loading dependencies".
I'm running it on Jupyter notebook on IE browser.
Could anyone explain me, where I'm going wrong?
Thanks all in advance.
I've tried running a sample code from "https://www.datacamp.com/community/tutorials/learn-build-dash-python"
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
df= pd.read_excel("https://github.com/chris1610/pbpython/blob/master/data/salesfnnel.xlsx?raw=True")
mgr_options = df["Manager"].unique()
app = dash.Dash()
app.layout = html.Div([
html.H2("Sales Funnel Report"),
html.Div(
[
dcc.Dropdown(
id="Manager",
options=[{
'label': i,
'value': i
} for i in mgr_options],
value='All Managers'),
],
style={'width': '25%',
'display': 'inline-block'}),
dcc.Graph(id='funnel-graph'),
])
#app.callback(
dash.dependencies.Output('funnel-graph', 'figure'),
[dash.dependencies.Input('Manager', 'value')])
def update_graph(Manager):
if Manager == "All Managers":
df_plot = df.copy()
else:
df_plot = df[df['Manager'] == Manager]
pv = pd.pivot_table(
df_plot,
index=['Name'],
columns=["Status"],
values=['Quantity'],
aggfunc=sum,
fill_value=0)
trace1 = go.Bar(x=pv.index, y=pv[('Quantity', 'declined')], name='Declined')
trace2 = go.Bar(x=pv.index, y=pv[('Quantity', 'pending')], name='Pending')
trace3 = go.Bar(x=pv.index, y=pv[('Quantity', 'presented')], name='Presented')
trace4 = go.Bar(x=pv.index, y=pv[('Quantity', 'won')], name='Won')
return {
'data': [trace1, trace2, trace3, trace4],
'layout':
go.Layout(
title='Customer Order Status for {}'.format(Manager),
barmode='stack')
}
if __name__ == '__main__':
app.run_server(debug=True, use_reloader = False)
Error in loading dependencies.

KivyMD 'MDMenuItem' object has no attribute 'text'

I want to click MDMenuItem to get text or do something.
But an error say "AttributeError: 'MDMenuItem' object has no attribute 'text' "
.py file like this
class MDMenuItem(Widget):
pass
class MyScreen(Screen):
menu_items = [
{'viewclass': 'MDMenuItem',
'text': 'text1'},
{'viewclass': 'MDMenuItem',
'text': 'text2'},
]
def change_variable(self, value):
print("\nvalue=", value)
self.VARIABLE = value
print("\tself.VARIABLE=", self.VARIABLE)
.kv file like this:
#:import MDDropdownMenu kivymd.menu.MDDropdownMenu
#:import MDRaisedButton kivymd.button.MDRaisedButton
<MDMenuItem>:
on_release: root.change_variable(self.text)
<MyScreen>:
name: myscrn
MDRaisedButton:
size_hint: None, None
size: 3 * dp(48), dp(48)
text: 'MDButton'
opposite_colors: True
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
on_release: MDDropdownMenu(items=root.menu_items, width_mult=4).open(self)
What should I do?
Edit:
Thank you for your reply. In my case, this .py subprogram not content 'App'. I don't want to put the method into main.py because I want main.py to stay clean.(Just content import, builder.load_file, add_wiget...)
So I want to call method without use 'app.something'.
Can I use root.something or other methods to call change_variable and get text?
I removed class MDMenuItem and change "root.change_variable" to "app.root.get_screen('MyScreen').change_variable". It's work!!!
The "app.root" treated as "screen.manager" in this case. I don't know why but it just work.
.py
class MyScreen(Screen):
menu_items = [
{'viewclass': 'MDMenuItem',
'text': 'text1'},
{'viewclass': 'MDMenuItem',
'text': 'text2'},
]
def change_variable(self, value):
print("\nvalue=", value)
self.VARIABLE = value
print("\tself.VARIABLE=", self.VARIABLE)
.kv
#:import MDDropdownMenu kivymd.menu.MDDropdownMenu
#:import MDRaisedButton kivymd.button.MDRaisedButton
<MDMenuItem>:
on_release: app.root.get_screen("MyScreen").change_variable(self.text)
Note:
The following solution is using KivyMD version 0.1.2.
AttributeError
AttributeError: 'MDMenuItem' object has no attribute 'text'
The error was due wrong definition for class MDMenuItem. It was defined with an inheritance of a Widget which does not has the attribute, 'text'.
Actual Definition of MDMenuItem
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.button import ButtonBehavior
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
class MDMenuItem(RecycleDataViewBehavior, ButtonBehavior, BoxLayout):
text = StringProperty()
Solution
There is no need to define class MDMenuItem in main.py. Remove it and the program will run.
Example
main.py
from kivy.app import App
from kivymd.theming import ThemeManager
from kivy.uix.screenmanager import Screen
class MyScreen(Screen):
VARIABLE = ""
menu_items = [
{'viewclass': 'MDMenuItem',
'text': 'text1'},
{'viewclass': 'MDMenuItem',
'text': 'text2'},
]
def change_variable(self, value):
print("\nvalue=", value)
self.VARIABLE = value
print("\tself.VARIABLE=", self.VARIABLE)
class MainApp(App):
title = "KivyMD MDDropdownMenu Demo"
theme_cls = ThemeManager()
def build(self):
return MyScreen()
if __name__ == "__main__":
MainApp().run()
main.kv
#:kivy 1.11.0
#:import MDDropdownMenu kivymd.menu.MDDropdownMenu
#:import MDRaisedButton kivymd.button.MDRaisedButton
<MDMenuItem>:
on_release: app.root.change_variable(self.text)
<MyScreen>:
name: 'myscrn'
MDRaisedButton:
size_hint: None, None
size: 3 * dp(48), dp(48)
text: 'MDButton'
opposite_colors: True
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
on_release: MDDropdownMenu(items=root.menu_items, width_mult=4).open(self)
Output

Resources