Repository: napari/napari

Issue:
Changing the axis slider label does not emit the axis_labels event
## 🐛 Bug

Changing the axis slider label does not cause the `Dims.events.axis_labels` event to be emitted, though `Dims.axis_labels` are updated. This means anyone listening to changes to axis labels will be unaware of the change in this case.

## To Reproduce

Here's one of the existing tests in `test_qt_dims` with some updates to reproduce the issue:

```python
def test_update_dims_labels(qtbot):
    """
    Test that the slider_widget axis labels are updated with the dims model
    and vice versa.
    """
    ndim = 4
    view = QtDims(Dims(ndim=ndim))
    qtbot.addWidget(view)
    view.dims.axis_labels = list('TZYX')
    assert [w.axis_label.text() for w in view.slider_widgets] == list('TZYX')

    observed_axis_labels_event = False

    def on_axis_labels_changed():
        nonlocal observed_axis_labels_event
        observed_axis_labels_event = True

    view.dims.events.axis_labels.connect(on_axis_labels_changed)
    first_label = view.slider_widgets[0].axis_label
    assert first_label.text() == view.dims.axis_labels[0]
    first_label.setText('napari')
    assert first_label.text() == view.dims.axis_labels[0]
    assert observed_axis_labels_event
```

## Expected behavior

The `Dims.events.axis_labels` to be emitted when the axis slider label is changed.

## Environment

This is on main at commit 3ec4be1ae8eee50ab4912ba87981261cc94c075f

## Additional context


Found while working on a plugin (https://github.com/andy-sweet/napari-metadata/issues/25).


Discussion:
Assigned to myself, as I have a fix incoming shortly

Resolving patch:
diff --git a/napari/_qt/widgets/qt_dims.py b/napari/_qt/widgets/qt_dims.py
--- a/napari/_qt/widgets/qt_dims.py
+++ b/napari/_qt/widgets/qt_dims.py
@@ -176,7 +176,9 @@ def _create_sliders(self, number_of_sliders: int):
         for slider_num in range(self.nsliders, number_of_sliders):
             dim_axis = number_of_sliders - slider_num - 1
             slider_widget = QtDimSliderWidget(self, dim_axis)
-            slider_widget.axis_label_changed.connect(self._resize_axis_labels)
+            slider_widget.axis_label.textChanged.connect(
+                self._resize_axis_labels
+            )
             slider_widget.play_button.play_requested.connect(self.play)
             self.layout().addWidget(slider_widget)
             self.slider_widgets.insert(0, slider_widget)
diff --git a/napari/_qt/widgets/qt_dims_slider.py b/napari/_qt/widgets/qt_dims_slider.py
--- a/napari/_qt/widgets/qt_dims_slider.py
+++ b/napari/_qt/widgets/qt_dims_slider.py
@@ -35,7 +35,6 @@ class QtDimSliderWidget(QWidget):
     This widget *must* be instantiated with a parent QtDims.
     """
 
-    axis_label_changed = Signal(int, str)  # axis, label
     fps_changed = Signal(float)
     mode_changed = Signal(str)
     range_changed = Signal(tuple)
@@ -193,13 +192,10 @@ def _pull_label(self):
         """Updates the label LineEdit from the dims model."""
         label = self.dims.axis_labels[self.axis]
         self.axis_label.setText(label)
-        self.axis_label_changed.emit(self.axis, label)
 
     def _update_label(self):
         """Update dimension slider label."""
-        with self.dims.events.axis_labels.blocker():
-            self.dims.set_axis_label(self.axis, self.axis_label.text())
-        self.axis_label_changed.emit(self.axis, self.axis_label.text())
+        self.dims.set_axis_label(self.axis, self.axis_label.text())
 
     def _clear_label_focus(self):
         """Clear focus from dimension slider label."""


Test patch:
diff --git a/napari/_qt/widgets/_tests/test_qt_dims.py b/napari/_qt/widgets/_tests/test_qt_dims.py
--- a/napari/_qt/widgets/_tests/test_qt_dims.py
+++ b/napari/_qt/widgets/_tests/test_qt_dims.py
@@ -252,11 +252,18 @@ def test_update_dims_labels(qtbot):
     view.dims.axis_labels = list('TZYX')
     assert [w.axis_label.text() for w in view.slider_widgets] == list('TZYX')
 
+    observed_axis_labels_event = False
+
+    def on_axis_labels_changed():
+        nonlocal observed_axis_labels_event
+        observed_axis_labels_event = True
+
+    view.dims.events.axis_labels.connect(on_axis_labels_changed)
     first_label = view.slider_widgets[0].axis_label
     assert first_label.text() == view.dims.axis_labels[0]
     first_label.setText('napari')
-    # first_label.editingFinished.emit()
     assert first_label.text() == view.dims.axis_labels[0]
+    assert observed_axis_labels_event
 
 
 def test_slider_press_updates_last_used(qtbot):