Is it possible to get the current position of an ipywidget? - python

I'm using the ipyvuetfy lib that create nice dashboarding element based ont he vuetify.js lib and ipyvwidgets.
I need to place a dialog in a specific position (on top of another element) like this menu placed on top of a select folder btn.
How can I access the the current position of a widget relative to the window ?

It is possible with Javascript code, by identifying the widget with a custom class and using the jQuery offset() method, and then setting the DOM Style top and left properties of the child (here a Card) of the ipyvuetify Dialog, with the style position set as fixed. I haven't found how to execute the JS code via the Dialog activator slot, so the Dialog widget is triggered via the click.stop event:
import ipyvuetify as v
import ipywidgets as w
from IPython.display import Javascript
out = w.Output(layout={'display': 'none'})
js = '''
var x = $(".myparentwidget").offset();
var d = document.getElementsByClassName("mydialog")[0];
d.style.top = x.top+"px";
d.style.left= x.left+"px";'''
def on_click(widget, event, data):
dialog.v_model=True
with out:
display(Javascript(js, lib="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"))
btn = v.Btn(
children=["Open dialog"],
class_='myparentwidget'
)
btn.on_event("click.stop", on_click)
dialog = v.Dialog(
v_model=False,
children=[
v.Card(
class_='mydialog',
style_="position: fixed; width: 300px",
children=[
v.CardTitle(children=["Dialog window"]),
v.CardText(children=['Dialog text']),
]
)
],
)
v.Layout(children=[btn,dialog,out])

Related

Streamlit all buttons are the same

import streamlit as st
import base64
def custom_button(text='button', bgpng=None, height='height: 225px;', width='width: 225px'):
with open (bgpng, 'rb') as img:
convert_img = base64.b64encode(img.read()).decode('utf-8')
background_img = f"background-image: url('data:image/png;base64, {convert_img}');"
st.markdown(f"""
<style>
div.stButton > button:first-child {{
{background_img}
{height}
{width}
}}
</style>""", unsafe_allow_html=True)
button = st.button(text)
return button
button1 = custom_button(text='button', bgpng=r'data\pic1.png')
button2 = custom_button(text='button2', bgpng=r'data\pic2.png')
The problem is the following, the last button always determines the properties of the other buttons, in this case the background image of button2 determines the background image of button1. So all buttons have the same background image. How can i solve it?
You create x styles for x buttons so the last style is applyed since it's the same priority.
I don't use python but I guess you could set an id for your buttons and apply your styles to #{button_id} (or something like that), or apply inline style like below :
<button style="background-color:orange;">button</button>
<button style="background-color:grey;">button2</button>
I found a solution.
If the streamlit code is ready, in the browser, right click, inspect , copy the css selector, then we get the unique button css selector. We need to replace this piece of code:
"div.stButton > button:first-child"
Should be replaced with: "copied css selector"
We have to do it for each button.

Insert UI elements into existing layouts

I want to insert a button into the main status line in Maya, it is the line where the functions like, save scene, vertex snap, open render view and stuff like this is(screenshot).
I already can add a button to the line, but it gets appended all the way to the right.
But how do I insert it between already existing buttons?
I want for example that my button is between the "Open Renderview" and "Render the current frame" button.
The code adds a button to the status line in Maya:
import maya.cmds as cmds
MainStatusLineLayoutChildren = cmds.layout('MainStatusLineLayout', query = True, childArray = True)
a = cmds.layout(MainStatusLineLayoutChildren[0], query = True, childArray = True)
cmds.nodeIconButton('testIconButton', style = 'iconOnly', image1 = 'file.png', parent = a[0])

Dash modal with multiple buttons that open it

Following this part of the docs: https://dash-bootstrap-components.opensource.faculty.ai/l/components/modal I've created a modal in my Dash app. The trigger for the modal will be dynamically rendered thumbnails. When any of them is clicked, the modal should open and display the image from the thumbnail as it's body.
Is is possible, inside Dash, to have multiple buttons (I don't know how many will there be, depending on how many thumbnails in the database) that will all open the same modal dialog and pass some of their data to the modal (such as img src in my case)?
The input in the example above is simple:
[
Input("open", "n_clicks"), Input("close", "n_clicks")
],
but in reality I don't know how many will there be and can't hardcode an ID.
Any suggestions?
Yes, you can have multiple buttons open a modal. Just as you showed, the callback would have an Input for each one. No, you cannot create them dynamically. Dash does not play well with any ID that is not in the layout at the start of running the app.
Create a set of buttons dynamically using the below list comprehension:
[dcc.Button(x, id={'type': 'thumbnail_button', 'index': x}) for x in thumbnail_list]
Use the pattern-matching callback to open modal when any of these buttons are clicked:
#app.callback(
Output('your-modal', 'is_open'),
[Input({'type': 'thumbnail_button', 'index': ALL}, 'n_clicks')]
)
def handle_button_click(n_clicks):
invoker = [p['prop id'] for p in dash.callback_context.triggered][0]
invoker_type = json.loads(invoker.split('.')[0])['type']
invoker_index = json.loads(invoker.split('.')[0])['index']
if invoker_type == "thumbnail_button":
return not is_open
else:
return is_open
Lastly the imports:
from dash.dependencies import Input, Output, ALL

IPython nbwidgets: Toggle Visiblity by button click

I'm using the ToggleButton and want to link it's value to the visilbiity of another widget.
I've come accross the Widget Events, but it is unclear to me how to bind the style property of the other widget to the value of the ToggleButton.
Has anyone done something similar?
I would use an observe call on the ToggleButton to change the visibility of the other widget. A simple example below.
toggle = ipyw.ToggleButton(description='Toggle visible')
to_hide = ipyw.IntRangeSlider(description = 'hide me')
display(to_hide)
display(toggle)
def hide_slider(widg):
if widg['new']:
to_hide.layout.display = 'none'
else:
to_hide.layout.display = ''
toggle.observe(hide_slider, names=['value'])

python: Right Click on list menu not showing item selected

In my ongoing effort to learn more about python, I am trying to add a right click event to my mp3 manager program. What currently works is that it shows the menu and all of the options. What is not working is the functions selected from the menu are not executing as I think they should be. Much of this code was taken from a 'how to' on another site.
Here are the right click menu options
menu_titles = ["Remove Selection from list",
"Delete Selection from system",
"Move Selection",
"Copy Selection",
"Print Selection"]
menu_title_by_id = {}
for title in menu_titles:
menu_title_by_id[ wxNewId() ] = title
The code that is run when the right click event happens
def RightClickCb( self, event ):
# record what was clicked
self.list_item_clicked = right_click_context = event.GetText()
### 2. Launcher creates wxMenu. ###
menu = wxMenu()
for (id,title) in menu_title_by_id.items():
### 3. Launcher packs menu with Append. ###
menu.Append( id, title )
### 4. Launcher registers menu handlers with EVT_MENU, on the menu. ###
EVT_MENU( menu, id, self.MenuSelectionCb )
### 5. Launcher displays menu with call to PopupMenu, invoked on the source component, passing event's GetPoint. ###
self.MainPanel.PopupMenu( menu, event.GetPoint() )
menu.Destroy() # destroy to avoid mem leak
def MenuSelectionCb( self, event ):
# do something
operation = menu_title_by_id[ event.GetId() ]
target = self.list_item_clicked
print 'Perform "%(operation)s" on "%(target)s."' % vars()
What I expect to get when I do a right-click and then select one of the options in the menu is the output
Perform "Print Selection" on "<data about the selection here>"
What I am getting is
Perform "Print Selection" on "."
How do I get the data from the item I have selected as part of my right click event?
Maybe you should use event.GetString() in place of event.GetText()
See here
Your code seems outdated tho, binding to events should be done like this:
menu.Bind(wx.EVT_MENU, self.MenuSelectionCb, id=id)
moreover if you bind all ids to the same function you can just bind once for all ids:
menu.Bind(wx.EVT_MENU, self.MenuSelectionCb)
You can find a solution under Python: Right click on objectlistview not showing item name selected where the use of objectlistview's GetSelectedObject() method is proposed instead.

Categories