13.1.13. Editorul de setări#
Multe aplicații pentru cameră au nevoie de câteva setări pe care un non-programator le poate schimba – un prag, un mod, o parolă Wi-Fi – fără a atinge scriptul. OpenMV Cam Settings Editor este instrumentul IDE-ului pentru asta: un fișier JSON descrie controalele, editorul transformă acea descriere într-un formular, iar scriptul tău citește valorile salvate cu json.load(). Fișierul este atât configurația, cât și definiția propriului său editor, astfel încât aceeași configurație care stochează valorile stabilește și aspectul interfeței pentru editarea lor.
Submeniul Tools → OpenMV Cam Settings Editor conține cele trei acțiuni ale sale.
Open OpenMV Cam Settings Config File citește configurația de pe unitatea camerei conectate și o deschide în editor; salvarea o scrie înapoi pe cameră.
Open Config File face același lucru pentru un fișier
.jsonde pe computerul tău, pentru pregătirea unei configurații offline.Create Default Config scrie o configurație de pornire pe disc și o deschide – un exemplu care exersează fiecare tip de control, gata de a fi redus la setările de care are nevoie propria aplicație.

Editorul de setări cu configurația implicită deschisă – controalele fișierului JSON dispuse sub forma unui formular (file, glisoare, liste derulante, casete de bifat), cu Save și Cancel în partea de jos.#
13.1.13.1. Anatomia unui fișier de configurație#
Un fișier de configurație este un singur obiect JSON cu două chei:
title (string, opțional) – titlul ferestrei editorului. Valoarea implicită este
OpenMV Cam Settings Editor.controls (array, obligatoriu) – lista obiectelor de control pe care editorul le redă, în ordine, ca rânduri ale unui formular. Aceasta este întreaga interfață grafică.
{
"title": "Camera Settings",
"controls": [
{ "type": "slider", "name": "threshold", "label": "Threshold", "value": 50 },
{ "type": "checkbox", "name": "draw_overlays", "label": "Draw Overlays", "value": true }
]
}
Fiecare intrare din controls este un control – un câmp de text, un număr, o casetă de bifare, un meniu derulant, un glisor, un grup, o bandă de file, o etichetă statică și așa mai departe. type-ul său selectează widgetul; restul obiectului îl configurează. Orice chei pe care editorul nu le recunoaște sunt lăsate neatinse când fișierul este salvat, astfel încât vă puteți păstra propriile metadate în fișier alături de controale.
13.1.13.3. Salvarea și citirea valorilor#
Un control care deține o valoare – o casetă de bifare, un glisor, un câmp de text – o poartă într-o cheie value. Când faceți clic pe Save, editorul scrie value-ul curent al fiecărui control direct înapoi în același obiect de control, la locul lui, și rescrie fișierul. Fișierul își păstrează structura: nimic nu se mută, se schimbă doar cheile value. Nu există o hartă plată separată de la name la valoare – valorile trăiesc în interiorul controalelor, exact acolo unde sunt definite.
De aceea aranjamentul contează pentru scriptul dumneavoastră. Tablourile controls și tabs păstrează ordinea în care le-ați construit, astfel încât fișierul nu poate fi indexat după nume ca un dicționar – config["controls"]["threshold"] nu funcționează. Această mică funcție auxiliară acoperă lacuna: dați-i calea numelor până la valoarea dorită, iar ea parcurge arborele în locul dumneavoastră.
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"]
Fiecare pas din cale este un name al unui control sau un title al unei file (o filă nu preia niciun name propriu, deși puteți adăuga unul și este păstrat). Banda de file și orice group pe care nu l-ați denumit sunt transparente – find le parcurge – așa că enumerați doar filele și controalele pe care le-ați etichetat, apropiat de o căutare imbricată config[...][...]. Un group denumit este un pas de sine stătător, așa că find poate returna și valoarea casetei sale de bifare. Dați fiecărui control un name unic, astfel încât o cale să nu fie niciodată ambiguă. Exemplu complet citește valori din aranjamentul demonstrativ imbricat.
Deoarece configurația este JSON simplu, nimic din scriptul dumneavoastră nu depinde de editor – editorul doar scrie fișierul pe care scriptul dumneavoastră îl citește deja. Un dispozitiv își poate purta configurația și un mod prietenos de a o schimba, în timp ce scriptul rămâne un simplu cititor de valori.
Un singur tip de control își impune intrarea la Save: un lineedit cu o mask sau regex refuză să lase editorul să salveze cât timp textul său este nevalid sau incomplet și denumește câmpurile de corectat. Orice alt control restrânge intrarea pe măsură ce editați – un glisor nu poate ieși din intervalul său, un spinbox se fixează în limitele sale – astfel încât un fișier salvat este întotdeauna valid.
13.1.13.4. Referință pentru fișierul de configurație#
Tipurile de control sunt documentate pe paginile de mai jos, grupate după ceea ce fac.