13.1.13. O editor de configurações#
Muitas aplicações de câmera precisam de um punhado de configurações que um não programador possa alterar – um limiar, um modo, uma senha de Wi-Fi – sem tocar no script. O OpenMV Cam Settings Editor é a ferramenta do IDE para isso: um arquivo JSON descreve os controles, o editor transforma essa descrição em um formulário, e seu script lê os valores salvos de volta com json.load(). O arquivo é tanto a configuração quanto a definição de seu próprio editor, então a mesma configuração que armazena os valores também organiza a GUI para editá-los.
O submenu Ferramentas → OpenMV Cam Settings Editor contém suas três ações.
Open OpenMV Cam Settings Config File lê a configuração da unidade da câmera conectada e a abre no editor; salvar a grava de volta na câmera.
Open Config File faz o mesmo para um arquivo
.jsonno seu computador, para preparar uma configuração offline.Create Default Config grava uma configuração inicial no disco e a abre – um exemplo que exercita todos os tipos de controle, pronto para ser reduzido às configurações que sua própria aplicação precisa.

O editor de configurações com a configuração padrão aberta – os controles do arquivo JSON dispostos como um formulário (abas, controles deslizantes, menus suspensos, caixas de seleção), com Save e Cancel na parte inferior.#
13.1.13.1. Anatomia de um arquivo de configuração#
Um arquivo de configuração é um único objeto JSON com duas chaves:
title (string, opcional) – o título da janela do editor. Assume por padrão
OpenMV Cam Settings Editor.controls (array, obrigatório) – a lista de objetos de controle que o editor renderiza, em ordem, como linhas de um formulário. Esta é toda a interface gráfica.
{
"title": "Camera Settings",
"controls": [
{ "type": "slider", "name": "threshold", "label": "Threshold", "value": 50 },
{ "type": "checkbox", "name": "draw_overlays", "label": "Draw Overlays", "value": true }
]
}
Cada entrada em controls é um controle – um campo de texto, um número, uma checkbox, uma lista suspensa, um slider, um group, uma faixa de abas, um label estático e assim por diante. Seu type seleciona o widget; o restante do objeto o configura. Quaisquer chaves que o editor não reconhecer permanecem intocadas quando o arquivo é salvo, de modo que você pode manter seus próprios metadados no arquivo junto com os controles.
13.1.13.3. Salvando e lendo valores#
Um controle que armazena um valor – uma checkbox, um slider, um campo de texto – o carrega em uma chave value. Quando você clica em Save, o editor grava o value atual de cada controle diretamente de volta nesse mesmo objeto de controle, no lugar, e reescreve o arquivo. O arquivo mantém sua estrutura: nada se move, apenas as chaves value mudam. Não existe um mapa plano separado de name para valor – os valores vivem dentro dos controles, exatamente onde são definidos.
É por isso que o layout importa para o seu script. Os arrays controls e tabs mantêm a ordem em que você os construiu, de modo que o arquivo não pode ser indexado por nome como um dicionário – config["controls"]["threshold"] não funciona. Este pequeno auxiliar preenche a lacuna: dê a ele o caminho de nomes até o valor desejado, e ele percorre a árvore por você.
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"]
Cada etapa do caminho é o name de um controle ou o title de uma aba (uma aba não possui um name próprio, embora você possa adicionar um e ele seja mantido). A barra de abas e qualquer group que você não nomeou são transparentes – find percorre-os – portanto você lista apenas as abas e os controles que rotulou, algo próximo de uma consulta config[...][...] aninhada. Um group nomeado é uma etapa em si, portanto find também pode retornar o valor de sua caixa de seleção. Dê a cada controle um name único para que um caminho nunca seja ambíguo. O Exemplo completo lê valores do layout de demonstração aninhado.
Como a configuração é JSON simples, nada no seu script depende do editor – o editor apenas grava o arquivo que seu script já lê. Um dispositivo pode carregar sua configuração e uma maneira amigável de alterá-la, enquanto o script continua sendo um simples leitor de valores.
Um tipo de controle impõe sua entrada ao salvar: um lineedit com uma mask ou regex se recusa a deixar o editor salvar enquanto seu texto estiver inválido ou incompleto, e nomeia os campos a corrigir. Todo outro controle restringe a entrada conforme você edita – um slider não pode sair de seu intervalo, um spinbox se limita aos seus limites – de modo que um arquivo salvo é sempre válido.
13.1.13.4. Referência do arquivo de configuração#
Os tipos de controle estão documentados nas páginas abaixo, agrupados pelo que fazem.