Calculating default values after form load

In QGIS desktop you can use a python function to update values in a form when other values are changed not just when the form is loaded. Is there any way to achieve this sort of behaviour in Qfield?

As context I want to set some default but user adjustable values based on the tree species surveyed but as the species is added after form is loaded the the defaults won’t update. I would also like to set some data dependent advice to teh surveyor in HTML/QML widgets but the issue is the same.

How are you using python to achieve this?

This seems like a good use of “relations”, not only on QField, but on QGIS itself. If you want to create a widget to easily list and access some features related to the current feature, check this page on the documentation to see if it helps you out.

If you are just trying to create some “interdepence” between two attributes of the same feature, you can use the Default value of each attribute to be populated with the value of the other.

For the default values, I think the best would be to either use a Value Map or Value Relation type of widget (the later gives you autocomplete functionality). For this and the previous point, you can check this tutorial or this other one to get an idea of how to set them up and how they work.

My understanding (as per the question and it’s title) is that default values are only applied at the point of form load, I am using them for other functionality. Using a relation might work for some of what I want to do but it won’t give a ‘live’ update.

live slider

This rough demo is achieved in the desktop, not Qfield, using a python function something like this

from qgis.PyQt.QtWidgets import QLabel, QSlider


def formOpen(dialog, layer, feature):
    slider = dialog.findChild(QSlider, 'stable_gr_slider')
    label_value = dialog.findChild(QLabel, 'label_stable_gr_value')
    label_times10 = dialog.findChild(QLabel, 'label_stable_gr_times10')

    if not slider or not label_value or not label_times10:
        return

    stable_gr_index = feature.fields().indexFromName('stable_gr')

    def update_labels(value):
        stable_gr = value / 100.0
        label_value.setText(f'Value: {stable_gr:.2f} m')
        label_times10.setText(f'Times 10: {stable_gr * 10:.2f}')
        if stable_gr_index != -1:
            feature.setAttribute(stable_gr_index, stable_gr)

    existing = None
    if stable_gr_index != -1:
        try:
            existing = feature.attribute(stable_gr_index)
        except Exception:
            existing = None

    if existing is not None:
        try:
            slider.setValue(int(round(float(existing) * 100)))
        except (TypeError, ValueError):
            slider.setValue(0)
    else:
        slider.setValue(0)

    update_labels(slider.value())
    slider.valueChanged.connect(update_labels)

You can easily replicate this with the Default Value option in Attributes Form as @cuprico mentioned.
Assuming Stable gr is of fieldtype integer you can:
Set up the Attributes Form for Stable gr to be a Range Widget with a slider
Set up the Attributes Form for Value to be a Text edit widget and have a Default value being “Stable gr” / 10
And check Apply Default on update

Now Value will immediately update whenever you move the slider.

Only issue here is that the field “Stable gr” has to be an integer. QGIS has long standing issues with real values (doubles) and the Range widget not working properly.
I think this has to do with the Geopackage implementation of real values and how QGIS sees those, see also this issue I created for QGIS a while ago: field domain range in a gpkg reverts to field type integer and causes data corruption · Issue #56146 · qgis/QGIS · GitHub

Confirmed live updating of a default value does work with with integers - thanks @Jeroen-GroeneBij , but won’t work for me unless I change my units around and add extra fields - I was hoping to display updating messages in a HTML or QML widget but I think I can make things work.

Just to be sure, in this example only “Stable gr” has to be an integer. All dependent fields such as Value and Times 10 can be of type real. Basically, the Range widget is the limiting factor here.

It will make it easier for people to think about growth in cm/year so I think all my growth rate values can be integers.

I think the bug you pointed to might be related to one I found a while ago Range widget bug

Now working with integers the Apply Default works as it should. I am never trusting Ai again.