QInstrumentWidget#

class QInstrument.lib.QInstrumentWidget.QInstrumentWidget(*args, device=None, **kwargs)[source]#

Bases: QWidget

Widget that auto-binds a Qt Designer UI to a QAbstractInstrument.

A named widget in the UI is linked to a registered device property when their names match and the widget type appears in wsetter, wgetter, and wsignal. User interaction with a linked widget calls device.set(); the device value is read back and the widget is updated without re-triggering the signal.

On first show, saved settings are reconciled with the hardware state via QReconcileDialog, and the device is moved to a dedicated worker thread so that serial I/O does not block the GUI. Settings are saved on close.

Subclass this, declare UIFILE, and supply a device:

class QDS345Widget(QInstrumentWidget):
    UIFILE = 'DS345.ui'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, device=QDS345(), **kwargs)

The .ui file is resolved relative to the subclass’s source directory, so it works regardless of the working directory.

Class Attributes#

UIFILEstr | None

Filename of the Qt Designer .ui file. Must be set by each subclass.

INSTRUMENTtype | None

Concrete instrument class to instantiate and search for when no device is supplied to __init__. When set, the base class calls INSTRUMENT().find() automatically so subclasses need not override __init__ solely to locate the device.

wsetterdict[str, str]

Maps widget class name to its value-setter method name.

wgetterdict[str, str]

Maps widget class name to its value-getter method name.

wsignaldict[str, str]

Maps widget class name to the signal emitted on user interaction.

Signals#

propertyChanged(str, object)

Emitted after a linked widget updates the device, carrying the property name and the new value.

wsetter = {'QCheckBox': 'setChecked', 'QComboBox': 'setCurrentIndex', 'QDoubleSpinBox': 'setValue', 'QGroupBox': 'setChecked', 'QLabel': 'setText', 'QLineEdit': 'setText', 'QPushButton': 'setChecked', 'QRadioButton': 'setChecked', 'QSpinBox': 'setValue'}#
wgetter = {'QCheckBox': 'isChecked', 'QComboBox': 'currentIndex', 'QDoubleSpinBox': 'value', 'QGroupBox': 'isChecked', 'QLabel': 'text', 'QLineEdit': 'text', 'QPushButton': 'isChecked', 'QRadioButton': 'isChecked', 'QSpinBox': 'value'}#
wsignal = {'QCheckBox': 'toggled', 'QComboBox': 'currentIndexChanged', 'QDoubleSpinBox': 'valueChanged', 'QGroupBox': 'toggled', 'QLineEdit': 'editingFinished', 'QPushButton': 'toggled', 'QRadioButton': 'toggled', 'QSpinBox': 'valueChanged'}#
UIFILE: str | None = None#
INSTRUMENT: type | None = None#
HARDWARE_DOMINANT: bool = False#
propertyChanged#

alias of str

device(device)#
properties()#

list[str]: device property names managed by this widget.

Return type:

list[str]

methods()#

list[str]: device method names managed by this widget.

Return type:

list[str]

settings(settings)#
get(key)[source]#

Return the current value of a named widget.

Parameters:

key (str) – Name of the property whose widget value to read.

Returns:

object or None – Current widget value, or None if key is not found.

set(key, value=None)[source]#

Set the value of a named widget.

When value is provided, sets the widget directly; the widget then emits its signal, which propagates the change to the device. When value is None, requests the current value from the device via device.get(); the result arrives via device.propertyValue and is applied by _onPropertyValue() with signals blocked.

Parameters:
  • key (str) – Name of the property to set.

  • value (bool | int | float | str | None, optional) – Value to apply. None (default) syncs the widget from the device.

Return type:

None

waitForDevice()[source]#

Block until the device has completed the most recent change.

Called by _setDeviceProperty() after every device write. The base implementation is a no-op; subclasses should override this if the instrument requires a settling delay.

Return type:

None

showEvent(event)[source]#

Reconcile device settings on first show.

On the first time the widget is shown, schedules _firstShow() via a zero-delay timer so that reconciliation runs after Qt has finished processing the show event. This avoids a crash caused by opening a modal dialog (nested event loop) from inside an event handler. Subsequent show events are passed through without reconciling.

Return type:

None

closeEvent(event)[source]#

Stop the worker thread and save settings when the widget is closed.

Stops the device worker thread before saving so that no queued slot calls arrive after the widget is gone. If the device has a stopPolling() slot, it is called before the thread is stopped; it only sets a flag, so it is safe from any thread. Saves using the current widget values (which reflect the last known device state) rather than querying the device directly, avoiding any cross-thread read. Only saves if the widget was previously shown, so that test widgets closed during teardown do not overwrite saved configuration.

Return type:

None

classmethod example()[source]#

Display the widget.

Creates a QApplication, instantiates the widget, shows it, and runs the event loop.

Intended to be called from __main__ in each widget module:

if __name__ == '__main__':
    QMyWidget.example()
Return type:

None