Estruturas da GUI - por thread

Saudações, colegas!

Há alguns meses, comecei a olhar para Golang com o objetivo de usá-lo para aplicativos de desktop. Gostei da linguagem, do volume e do assunto dos pacotes escritos para impressionar, mas a situação com a GUI não é tão otimista. Não vou me debruçar sobre os detalhes agora, basta dizer que, depois de ler algumas resenhas e dar uma rápida olhada nos pacotes existentes da GUI, decidi escrever meus próprios, especialmente porque tenho experiência nisso.

Meu primeiro pensamento foi seguir o caminho já trilhado: escrever um conjunto de funções correspondentes em C, ou melhor, adaptar um já pronto - o que escrevi para Harbor e C ++, vincular a ele usando cgo (C API para Golang) e invólucro amigável. Até comecei a fazer isso, recebi a primeira janela, mas como imaginava quanto trabalho ainda estava à frente, separadamente para Windows, separadamente para Linux, um trabalho puramente técnico, já que eu já havia passado por isso, meu entusiasmo esfriou um pouco.

E então outra idéia veio.

Eu já tenho uma biblioteca de GUI, HwGUI for Harbor, que é bastante funcional, multiplataforma, que eu uso regularmente para meus aplicativos. Tudo o que eu preciso já está implementado nele. Por que não escrever em sua base um programa que funciona como um tipo de servidor GUI. Depois de iniciar este servidor, ele escuta silenciosamente uma porta específica e, após receber uma conexão do meu programa Golang, cria janelas, widgets em resposta às suas solicitações, manipula-os e fornece feedback quando qualquer evento dos widgets aparecer - em uma palavra, implementar uma GUI para ele. Todos os detalhes de baixo nível da implementação da GUI já estão na biblioteca, para Windows - através de chamadas diretas para WinAPI, para Linux / Unix e, provavelmente, macOs - via GTK. Além disso, não pretendo criar um servidor no sentido pleno da palavra, ele não aceitará conexões de programas diferentes - isso introduziria dificuldades desnecessárias adicionais. Para cada instância do programa Golang, uma instância separada do servidor da GUI será iniciada, o que simplifica ainda mais a tarefa. Em geral, o programa consistirá, portanto, em dois processos, um dos quais executa a tarefa principal, o outro é responsável pela interface.

O pacote correspondente para Go deve incluir o procedimento Init, que inicia o servidor da GUI e o une, e um conjunto de estruturas, métodos, funções para criar janelas e widgets e manipulá-los. O conteúdo principal de todas essas funções é enviar mensagens de um determinado formato (baseado em JSON) para o servidor e receber mensagens dele. A comunicação é suportada usando duas portas tcp / ip, uma é responsável por enviar solicitações ao servidor e a outra por receber sinais do servidor para o processamento de eventos (pressionar um botão, fechar uma janela etc.). A tarefa é relativamente simples, o pacote em si é pequeno. Não é necessário usar o cgo, não é necessário vincular-se a bibliotecas de terceiros, todo o código no Go puro. O arquivo executável do próprio programa e o arquivo executável do servidor da GUI são todos.

A escolha do Harbor + HwGUI para a implementação do servidor da GUI para mim se deve principalmente ao fato de essas serem minhas ferramentas "nativas", a solução mais simples e rápida. Mas esta é uma boa escolha de outros pontos de vista. Aqui, na minha opinião, as principais vantagens:

  • multiplataforma "na caixa";
  • o que é chamado de aparência nativa, já que no Windows são chamadas exclusivamente WinAPI, no Linux / Unix - GTK; quanto o GTK "nativo" para macOs eu realmente não sei;
  • a capacidade de usar o Harbor como uma linguagem de script interna, você pode transferir fragmentos de código para execução para o servidor - manipuladores de eventos, por exemplo, que podem descarregar o programa principal a partir de alguns detalhes de implementação. Além disso, o Harbor é bom para muitas coisas, por trabalhar com o dbf e alguns bancos de dados, por exemplo;
  • implementação de impressão;
  • a capacidade de usar formulários de tela criados pelo Designer (utilitário HwGUI). Esses formulários são armazenados no formato XML e podem ser usados ​​sem alterações em qualquer SO no qual o servidor esteja sendo executado;
  • a capacidade de usar formulários de relatório criados pelo mesmo Designer para impressão (também em XML).

Em resumo, comecei a fazer isso e uma parte significativa do trabalho já foi concluída. Ambos os projetos, o GuiServer e a estrutura da GUI externa do Golang, estão no Github, todos os links estão no final do artigo. Abaixo estão algumas capturas de tela. Nada de especial, apenas testes.

Esta é uma caixa de diálogo simples:


E isso é feito com base em um exemplo do livro de Kernigan e Donovan:


Agora, o principal objetivo dos projetos é garantir que esse doce casal, External e GuiServer, possa fazer tudo o que a HwGUI pode fazer. Bem, no processo de criação de alguns aplicativos reais usando o External, ficará claro o que é necessário mais.

Este pode ser o fim, adiei a descrição do pacote Golang para outra ocasião. Mas a principal coisa neste artigo está apenas começando. Afinal, o método descrito para implementar uma estrutura da GUI com o mesmo servidor da GUI pode ser usado para outros idiomas. C, Python, Java, ..., até Perl e PHP (e por que não?) - veja o título do artigo. Custos mínimos - e uma solução GUI bastante funcional está pronta. O mais difícil para cada linguagem específica não é a implementação de uma troca com o servidor, mas que essa solução se encaixe organicamente em seu paradigma, em sua lógica interna. Se alguém quiser criar uma estrutura para seu idioma, tentarei fornecer toda a assistência possível na obtenção das informações necessárias e, possivelmente, na adição de alguns recursos ao servidor da GUI.

Paralelamente ao pacote Golang, fiz um análogo para o Harbor, principalmente para fins de verificação / depuração. É improvável que eu faça uma estrutura para Perl, mas para C ou C ++ é bem provável. E aqui está o porquê: afinal, há outro recurso interessante relacionado ao uso de um servidor GUI, que pode ser executado em outro computador. O programa principal é executado em um computador e sua interface em outro. Imediatamente visto aqui, existem opções para usar este caso:

  • o programa principal é executado em um servidor Linux / Unix no qual o shell gráfico não está instalado;
  • o programa principal é executado no computador de outra pessoa (com um contador condicional na sua empresa) e você, sem interferir com ele, o gerencia por conta própria;
  • o programa principal é executado em um smartphone e você explora o interior de um computador normal;
  • o programa principal é executado no controlador, em alguns Arduino, Raspberry ou em seus equivalentes, onde pode não haver monitor normal. Conecte-se ao seu laptop - e pronto.

Bem, para esta última opção, uma estrutura C para um servidor GUI provavelmente seria útil, acho que essa possibilidade é muito promissora.

E, finalmente, os links:

github.com/alkresin/guiserver - GuiServer no Github
github.com/alkresin/external - Externo (pacote Go) no Github
www.kresin.ru/guisrv.html - a página do GuiServer no meu site, aqui você pode baixar binários prontos
habr.com/post/198618 - meu artigo sobre Harbour está aqui em Habré
pt.wikipedia.org/wiki/Harbor - Porto na Wikipedia
www.kresin.ru/harbour.html - Página do porto no meu site
www.kresin.ru/hwgui.html - a página HwGUI no meu site

PS: Está claro que poucas pessoas instalarão o Harbor e o HwGUI para criar o GuiServer a partir da fonte, por isso eu publico regularmente os binários coletados na página do GuiServer no meu site - para Windows, Debian 8 de 32 bits, Ubuntu 18.04 de 64 bits. Posso montar no Fedora, mas no macOs - infelizmente, não o tenho a uma curta distância.

Source: https://habr.com/ru/post/pt427429/


All Articles