GUI universal ~ = fim da miséria

Para mim, a GUI ideal é um aplicativo que não requer programação, design, manutenção e é capaz de funcionar igualmente com qualquer idioma e em qualquer plataforma sem ajustes. É possível em nossa vida tentarmos descobrir isso.

É fácil aprender algo individualmente com Vue / React, JavaFX, Python PyQt, ... mas obter dados e interagir com o zoológico de software de uma maneira simples e elegante, sem pensar no sistema operacional do usuário / navegadores / plataformas, é uma tarefa não resolvida para essas ferramentas. Não quero entrar na nova estrutura (até a antiga, esquecida), alterando a linguagem de programação, varrendo o ancinho e entupindo minha cabeça com lixo. Quero programar exatamente minha tarefa, sem me distrair com a luta com todos os tipos de estruturas de GUI. E eu encontrei uma solução para mim.

Como um protocolo de troca, usaremos o Json como o formato principal em termos de popularidade / compreensibilidade / legibilidade / suporte para todas as linguagens de programação em um grau ou outro.

O servidor envia dados Json, segundo os quais a nossa GUI do aplicativo deve criar uma imagem que satisfaça as especificações de uma bela GUI. Hoje, o Google com seu design de materiais é o padrão, então aceite.

Os requisitos para uma GUI moderna incluem a presença de elementos padrão, como botões, campos de entrada, tabelas, etc. Vamos estimar como usar o conjunto mínimo de convenções para informar à GUI que precisamos de certos elementos na tela. Aqui estão os principais:

  • Botão sem estado {'name': 'Push me'}. Se o elemento contiver apenas um nome, será um botão.
  • O campo de entrada é {'name': 'Edit me', 'value': ''} porque o valor do tipo é uma sequência.
  • O botão do comutador {'name': 'My state', 'value': false} porque o tipo false é booleano.
  • Selecione na lista {'name': 'Alternar algo', valor: 'choice1', options = ['choice1', 'choice2', 'choice3']}
  • {‘name’:’Image, ‘url'’: ’..’, ‘width’: .., ‘height’:… }
  • {‘name’:’My table’, 'headers'=[‘Name’, ‘Synonym’], rows = [
    [‘young’, ‘youthful’],
    [‘small’, ‘ meager’],
    ...]
    }

Para personalização, você pode definir o tipo de elemento como {type: 'ButtonSwitcher'} se o tipo selecionado automaticamente pelo JSON não for adequado para você. Isso é possível quando o mesmo JSON pode ser exibido de mais de uma maneira. Por exemplo, 'Selecionar de uma lista' pode ser representado como um campo de entrada com uma lista suspensa ou também pode ser um conjunto horizontal de botões, um dos quais está ativo e corresponde ao valor atual.

Com um pequeno número de opções, faz sentido usar automaticamente a opção de botão, com um número grande (mais de 3) - um campo de seleção de entrada. Nossa própria GUI escolhe a melhor maneira de renderizar, mas se você realmente precisar dela - digite: ... para ajudar. Normalmente, o tipo não é necessário e o designer do carro deve lidar sozinho.

Vamos completar a imagem em detalhes:

  • se o nome não deve ser exibido na tela, ele deve começar com _;
  • - , ‘icon’: ‘ Material Design ’; push - {‘name’: ‘_Check’, ‘icon’: ‘check’}
  • , Viewers, , ‘colors’, ‘params’,… // . — , .

Para o agrupamento lógico de elementos, introduzimos o conceito de um bloco que agrupa elementos logicamente relacionados em um bloco visual.

{'name': 'Block 1', 'elems': [{'name': '_Check', 'icon': 'check'}, ...]}
Dentro do bloco, todos os elementos devem ter nomes exclusivos, porque são id .

Normalmente, os blocos são construídos horizontalmente, se eles não podem caber em tudo na tela (eles iniciaram a GUI do aplicativo em um celular, por exemplo), o designer de automóveis os oculta, mas adiciona ícones à barra de ferramentas para abri-los com um toque. Isso oferece a opção de trabalhar com uma GUI complexa, mesmo em telas pequenas.

O nível superior da descrição é Tela. Parece que {'name': 'Screan', bloqueia: [..], menu: [{'name': 'Screen', 'icon': ..,}, ..], 'toolbar': [JSON set - elementos (botões, campos, o que for)]}

Adicione detalhes de implementação para a uniGUI condicional que suporta nosso protocolo JSON. É um processo separado que se comunica com o servidor de dados Websocket e fornece a exibição de seus dados com relatórios subsequentes de todas as atualizações desses dados importantes para o servidor.

Ao se conectar ao servidor, o uniGUI espera receber a tela. Depois de recebê-lo, ele projeta e desenha as informações resultantes de uma maneira ideal para a tela atual do usuário e aguarda uma reação do usuário e do servidor. A partir da imagem de dados construída, o servidor recebe um fluxo de mensagens JSON que descrevem completamente o que o usuário fez. Eles têm a forma ['Block', 'Elem', 'tipo de ação', 'value'], onde 'Block' e 'Elem' são os nomes do bloco e do elemento, value é o valor do evento.

O servidor pode aceitar a alteração ou revertê-la enviando uma janela de informações sobre a discrepância. Ele pode gerar uma caixa de diálogo, descrita como um bloco, e possui adicional. o parâmetro 'buttons', que descreve os botões na caixa de diálogo. O cliente exibe instantaneamente os dados atuais do servidor e suas alterações. Apenas objetos alterados pelo servidor são enviados.Para receber eventos e garantir seu processamento, criaremos uma camada Websocket (framework), que converterá automaticamente as mensagens em chamadas para manipuladores que estão associados aos nossos dados (objetos).

Toda a mágica do servidor se resume ao fato de que nossos dados exibidos devem ser vinculados à camada de forma que, sem qualquer codificação, garanta sua tradução automática em JSON e chame notificações de retorno da atividade do usuário. Como depende dos recursos de um idioma específico, para cada idioma a camada pode ter opções diferentes, tanto arquitetural quanto especificamente.

Por exemplo, em um caso, a camada possui uma pasta de capturas de tela, cada um dos módulos nos quais tem uma descrição de uma tela no Python. Na inicialização, a camada lê as telas, fornece ao usuário uma prioridade global = 0. Todos os dados são transmitidos automaticamente usando o jsonpickle. Elementos complexos têm sua própria "inteligência", removendo o cuidado dos detalhes do programador. Por exemplo, uma tabela recebe um conjunto de linhas, nas quais, por padrão, a linha de identificação pode estar ausente quando o número de dados na linha == o número de elementos nos cabeçalhos. Nesse caso, quando o usuário seleciona uma linha ou edita seu conteúdo, o servidor envia a identificação para o índice na linha como id ee. Se o número de dados na linha for um a mais do que nos cabeçalhos, o último elemento nas linhas será interpretado como id e será enviado para o servidor. Essa automação simplifica muito a vida em que você não precisa de detalhes específicos,mas se você precisar de repente, ele estará disponível da maneira menos trabalhosa.

A tarefa de fornecer tradução automática em JSON, seguindo um formato que ocupa uma ou duas páginas, é completamente solucionável em qualquer idioma (espero que sim).

Para não discutir a aplicabilidade dessa abordagem para aplicativos complexos, abaixo estão as capturas de tela como as descritas pela uniGUI, escritas em flutter. A escolha recaiu sobre ele em várias plataformas e a falta de camadas adicionais, como JS / chrome. A vibração negativa pode ser um suporte de área de trabalho repugnante e baixa qualidade do código da camada superior (elementos da GUI), uma arquitetura desagradável para atualizações de pontos e gerenciamento de elementos como dados, que, no entanto, são tratados.



A GUI do aplicativo de fluxo de mensagens -> servidor é mais ou menos assim:

flutter: [Glossário, Termos, =, 658]
flutter: [_Detalhes, Links, @, @Folliculitis]
flutter: [_Detalhes, Links, @, @Adolescent]
flutter: [barra de ferramentas, _Back, =, _Back]
flutter: [barra de ferramentas, _Forward, =, _Forward]
flutter: [barra de ferramentas, _Back, =, _Back]
flutter: [_Detalhes, _Status, =, Virtual]
flutter: [_Detalhes, _Status , =, Virtual] flutter: [_Detalhes, _Status , =, Stable]
flutter: [_Detalhes, Links, @,Inflamação]
flutter: [_Details, _Status, =, Virtual]
flutter: [_Details, _Status, =, Stable]
flutter: [barra de ferramentas, _Back, =, _Back]
flutter: [_Details, Links, @, @Folliculitis]

Haverá desacelere essa GUI ao aguardar eventos do servidor. Não, porque a GUI funciona no modo de notificação do servidor, reagindo a todas as ações do usuário como uma GUI local normal. Por padrão, ele considera o silêncio do servidor nas ações do usuário como OK. Ao mudar de tela, fica claro que sua descrição deve vir. Pode haver um atraso em comparação com a GUI incorporada do aplicativo típico.

Total. Hoje, é possível, nas ferramentas atuais, criar uma GUI que remova 90% do código de serviço padrão padrão e não se preocupe onde e como ele funcionará. Pelo menos para aplicativos de negócios / ciências. Este artigo é uma prova de conceito de que a criação de um navegador de aplicativos condicional não é apenas possível, mas necessária.

All Articles