Repository: pyqtgraph/pyqtgraph

Issue:
`pen` parameter fires `sigValueChanged` without setting value
This line should be `setValue` rather than emitting `sigValueChanged`:
https://github.com/pyqtgraph/pyqtgraph/blob/8be2d6a88edc1e26b1f6f85c47a72c400db9a28b/pyqtgraph/parametertree/parameterTypes/pen.py#L52

In all other parameters, the signal doesn't fire until after the value is set.
`pen` parameter fires `sigValueChanged` without setting value
This line should be `setValue` rather than emitting `sigValueChanged`:
https://github.com/pyqtgraph/pyqtgraph/blob/8be2d6a88edc1e26b1f6f85c47a72c400db9a28b/pyqtgraph/parametertree/parameterTypes/pen.py#L52

In all other parameters, the signal doesn't fire until after the value is set.


Discussion:

Resolving patch:
diff --git a/pyqtgraph/parametertree/parameterTypes/pen.py b/pyqtgraph/parametertree/parameterTypes/pen.py
--- a/pyqtgraph/parametertree/parameterTypes/pen.py
+++ b/pyqtgraph/parametertree/parameterTypes/pen.py
@@ -1,26 +1,52 @@
 import re
 from contextlib import ExitStack
 
-from . import GroupParameterItem
+from . import GroupParameterItem, WidgetParameterItem
 from .basetypes import GroupParameter, Parameter, ParameterItem
 from .qtenum import QtEnumParameter
 from ... import functions as fn
-from ...Qt import QtCore
+from ...Qt import QtCore, QtWidgets
 from ...SignalProxy import SignalProxy
 from ...widgets.PenPreviewLabel import PenPreviewLabel
 
 class PenParameterItem(GroupParameterItem):
     def __init__(self, param, depth):
+        self.defaultBtn = self.makeDefaultButton()
         super().__init__(param, depth)
+        self.itemWidget = QtWidgets.QWidget()
+        layout = QtWidgets.QHBoxLayout()
+        layout.setContentsMargins(0, 0, 0, 0)
+        layout.setSpacing(2)
+
         self.penLabel = PenPreviewLabel(param)
+        for child in self.penLabel, self.defaultBtn:
+            layout.addWidget(child)
+        self.itemWidget.setLayout(layout)
+
+    def optsChanged(self, param, opts):
+        if "enabled" in opts or "readonly" in opts:
+            self.updateDefaultBtn()
 
     def treeWidgetChanged(self):
         ParameterItem.treeWidgetChanged(self)
         tw = self.treeWidget()
         if tw is None:
             return
-        tw.setItemWidget(self, 1, self.penLabel
-                         )
+        tw.setItemWidget(self, 1, self.itemWidget)
+
+    defaultClicked = WidgetParameterItem.defaultClicked
+    makeDefaultButton = WidgetParameterItem.makeDefaultButton
+
+    def valueChanged(self, param, val):
+        self.updateDefaultBtn()
+
+    def updateDefaultBtn(self):
+        self.defaultBtn.setEnabled(
+            not self.param.valueIsDefault()
+            and self.param.opts["enabled"]
+            and self.param.writable()
+        )
+
 
 class PenParameter(GroupParameter):
     """
@@ -49,7 +75,21 @@ def __init__(self, **opts):
         self.valChangingProxy = SignalProxy(self.sigValueChanging, delay=1.0, slot=self._childrenFinishedChanging)
 
     def _childrenFinishedChanging(self, paramAndValue):
-        self.sigValueChanged.emit(*paramAndValue)
+        self.setValue(self.pen)
+
+    def setDefault(self, val):
+        pen = self._interpretValue(val)
+        with self.treeChangeBlocker():
+            # Block changes until all are finalized
+            for opt in self.names:
+                # Booleans have different naming convention
+                if isinstance(self[opt], bool):
+                    attrName = f'is{opt.title()}'
+                else:
+                    attrName = opt
+                self.child(opt).setDefault(getattr(pen, attrName)())
+            out = super().setDefault(val)
+        return out
 
     def saveState(self, filter=None):
         state = super().saveState(filter)


Test patch: