-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
how to use annotation with create_widget #68
Changes from 8 commits
4e73155
8f1682f
5fd71e1
687b338
4d4b7f2
674a2c1
2bd13b8
52076db
033e55f
e3d9df9
a8b68e6
303d811
3c4e9e4
ab19235
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -178,6 +178,10 @@ The following napari types may be used as *parameter* type annotations in | |||||||||
{attr}`napari.types.ImageData` or {attr}`napari.types.LabelsData` | ||||||||||
- {class}`napari.Viewer` | ||||||||||
|
||||||||||
```{note} | ||||||||||
If you're interested in getting synchronized information from the napari viewer into widgets without `@magicgui`, see the [`create_widget` example](#magicgui-widgets-create_widget) below. | ||||||||||
``` | ||||||||||
|
||||||||||
The consequence of each type annotation is described below: | ||||||||||
|
||||||||||
#### Annotating as a `Layer` subclass | ||||||||||
|
@@ -783,3 +787,41 @@ viewer.window.add_dock_widget(my_widg) | |||||||||
|
||||||||||
As above to turn this into a [plugin widget contribution](widgets-contribution-guide), | ||||||||||
simply provide the class definition and add to the plugin manifest. | ||||||||||
|
||||||||||
#### `magicgui.widgets.create_widget` | ||||||||||
|
||||||||||
You might want to add a layer selection as [shown above](#parameter-annotations) into your highly customizable `QtWidgets.QWidget` that is always synchronized with the available {attr}`napari.types.ImageData` layers in your viewer. For this you can use the {func}`create_widget <magicgui.widgets.create_widget>` function as described in the following example. | ||||||||||
|
||||||||||
To synchronize the information between the napari viewer (i.e. the available layers) the function `reset_choices` of the dropdown widget needs to be connected to the `inserted`, `removed` and `reordered` events of the `viewer.layers` as is done in the `__init__` function below: | ||||||||||
|
||||||||||
```python | ||||||||||
import napari | ||||||||||
from magicgui.widgets import create_widget | ||||||||||
from qtpy.QtWidgets import QWidget, QHBoxLayout | ||||||||||
|
||||||||||
from napari.types import ImageData | ||||||||||
|
||||||||||
|
||||||||||
class ExampleLayerListWidget(QWidget): | ||||||||||
def __init__(self, viewer: "napari.viewer.Viewer"): | ||||||||||
super().__init__() | ||||||||||
self.viewer = viewer | ||||||||||
|
||||||||||
# create new widget with create_widget and type annotation | ||||||||||
self.layer_select = create_widget(annotation=ImageData) | ||||||||||
layers_events = self.viewer.layers.events | ||||||||||
layers_events.inserted.connect(self.layer_select.reset_choices) | ||||||||||
layers_events.removed.connect(self.layer_select.reset_choices) | ||||||||||
layers_events.reordered.connect(self.layer_select.reset_choices) | ||||||||||
Comment on lines
+799
to
+802
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe, we can explain that part of napari magic, too, and show both possibilities with a marker that one of them is potentially deprecated? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are working on nested Layers (Layer Groups). It may change a list of events. So then people will need to update their plugins if they do not depend on napari calling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
@Czaki I'm not happy to enshrine this behaviour in our docs right now (see original comment here). It's very brittle and in my opinion, quite an overreach that could lead to surprising effects on widgets totally unrelated to the layerlist. I would strongly prefer to keep the example as it currently is, because it involves no magic and no reliance on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we explain the shortcut via
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the offer @gatoniel —if we decide to take you up on it or parts of it, I think expanding on the reset_choices magic should come in a separate PR. For now I think we are still internally deciding whether we want it in the docs, as you can see 😅, so I think this should go in as-is. Regarding the future of the event connections: in my opinion, if we start worrying in the docs about all the things we are planning to deprecate, we will never document anything. 😂 I think in general the docs should be written with regard to the current public API, unless we really want to discourage use of a specific API. Which is not the case here. |
||||||||||
|
||||||||||
self.setLayout(QHBoxLayout()) | ||||||||||
# add it to the layout | ||||||||||
self.layout().addWidget(self.layer_select.native) | ||||||||||
|
||||||||||
# Create a `viewer` | ||||||||||
viewer = napari.Viewer() | ||||||||||
# Instantiate your widget | ||||||||||
my_widg = ExampleLayerListWidget(viewer) | ||||||||||
# Add widget to `viewer` | ||||||||||
viewer.window.add_dock_widget(my_widg) | ||||||||||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is necessary. I think we automatically update for all magicgui registered napari types; layer, layer subclasses and layer type data (e.g.,
napari.types.ImageData
).I am not sure if there would be any cases where you would want an input that is not in the above list.
If there is, we could mention that for non registered types you need to manually synchronize, see
QWidget
example for more...cc @DragaDoncila
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have made the note more precise. I added it, because I was aware that one can easily create these synchronized dropdown lists of the available layers with
@magicgui
. But then, they were part of a bigger widget, and I was not able to figure out to create only these widgets which is possible withcreate_widget
.