13.1.13. L’editor delle impostazioni#
Molte applicazioni per camere necessitano di una manciata di impostazioni che un non programmatore possa modificare – una soglia, una modalità, una password Wi-Fi – senza toccare lo script. L’OpenMV Cam Settings Editor è lo strumento dell’IDE per questo: un file JSON descrive i controlli, l’editor trasforma quella descrizione in un modulo e il tuo script rilegge i valori salvati con json.load(). Il file è sia la configurazione sia la definizione del proprio editor, così la stessa configurazione che memorizza i valori dispone anche la GUI per modificarli.
Il sottomenu Tools → OpenMV Cam Settings Editor contiene le sue tre azioni.
Open OpenMV Cam Settings Config File legge la configurazione dall’unità della camera connessa e la apre nell’editor; il salvataggio la riscrive sulla camera.
Open Config File fa lo stesso per un file
.jsonsul tuo computer, per preparare una configurazione offline.Create Default Config scrive una configurazione iniziale su disco e la apre – un esempio che mette alla prova ogni tipo di controllo, pronto per essere ridotto alle impostazioni di cui la tua applicazione ha bisogno.

L’editor delle impostazioni con la configurazione predefinita aperta – i controlli del file JSON disposti come un modulo (schede, cursori, menu a discesa, caselle di controllo), con Save e Cancel in fondo.#
13.1.13.1. Anatomia di un file di configurazione#
Un file di configurazione è un singolo oggetto JSON con due chiavi:
title (string, facoltativo) – il titolo della finestra dell’editor. Il valore predefinito è
OpenMV Cam Settings Editor.controls (array, obbligatorio) – l’elenco degli oggetti di controllo che l’editor visualizza, in ordine, come righe di un modulo. Questa è l’intera GUI.
{
"title": "Camera Settings",
"controls": [
{ "type": "slider", "name": "threshold", "label": "Threshold", "value": 50 },
{ "type": "checkbox", "name": "draw_overlays", "label": "Draw Overlays", "value": true }
]
}
Ogni voce in controls è un controllo – un campo di testo, un numero, una casella di spunta, un menù a discesa, uno slider, un gruppo, una barra di schede, un’etichetta statica e così via. Il suo type seleziona il widget; il resto dell’oggetto lo configura. Qualsiasi chiave che l’editor non riconosce viene lasciata intatta al salvataggio del file, quindi puoi conservare i tuoi metadati nel file insieme ai controlli.
13.1.13.3. Salvataggio e lettura dei valori#
Un controllo che contiene un valore – una casella di spunta, uno slider, un campo di testo – lo porta in una chiave value. Quando fai clic su Save, l’editor scrive il value corrente di ciascun controllo direttamente nello stesso oggetto di controllo, sul posto, e riscrive il file. Il file mantiene la sua struttura: nulla si sposta, cambiano solo le chiavi value. Non esiste una mappa piatta separata da name a valore – i valori risiedono all’interno dei controlli, esattamente dove sono definiti.
Ecco perché il layout è importante per il tuo script. Gli array controls e tabs mantengono l’ordine in cui li hai costruiti, quindi il file non può essere indicizzato per nome come un dizionario – config["controls"]["threshold"] non funziona. Questa piccola funzione ausiliaria colma il divario: forniscile il percorso di nomi fino al valore che desideri, e percorrerà l’albero al posto tuo.
import json
def find(node, *path):
"""Return the control at a path of names; read its value with
["value"]. The tab strip and any unnamed group are transparent,
so you list only the tabs and controls you gave a name."""
for key in path:
match = _child(node, key)
if match is None:
raise KeyError(key)
node = match
return node
def _child(node, key):
for member in node.get("controls", []) + node.get("tabs", []):
if member.get("name") == key or member.get("title") == key:
return member
if "name" not in member and ("controls" in member or "tabs" in member):
match = _child(member, key) # see through an unnamed group / the tab strip
if match is not None:
return match
return None
with open("config.json") as file:
config = json.load(file)
threshold = find(config, "threshold")["value"]
Ogni passo del percorso è il name di un controllo, oppure il title di una scheda (una scheda non ha un name proprio, anche se puoi aggiungerne uno e viene conservato). La barra delle schede e ogni group a cui non hai dato un nome sono trasparenti – find li attraversa – quindi elenchi solo le schede e i controlli che hai etichettato, in modo simile a una ricerca annidata config[...][...]. Un group con nome è un passo a sé, quindi find può anche restituire il valore della sua casella di controllo. Assegna a ogni controllo un name univoco affinché un percorso non sia mai ambiguo. La Esempio completo legge i valori dal layout dimostrativo annidato.
Poiché la configurazione è semplice JSON, nulla nel tuo script dipende dall’editor – l’editor si limita a scrivere il file che il tuo script già legge. Un dispositivo può portare con sé la propria configurazione e un modo semplice per modificarla, mentre lo script resta un semplice lettore di valori.
Un tipo di controllo impone il proprio input al salvataggio: una lineedit con una mask o una regex impedisce all’editor di salvare finché il suo testo è non valido o incompleto, e indica i campi da correggere. Ogni altro controllo vincola l’input durante la modifica – uno slider non può uscire dal suo intervallo, uno spinbox si limita ai suoi confini – quindi un file salvato è sempre valido.
13.1.13.4. Riferimento del file di configurazione#
I tipi di controllo sono documentati nelle pagine seguenti, raggruppati in base a ciò che fanno.