Questões de módulos

Ao trabalhar com um kit de ferramentas de widgets, é importante compreender o modelo de módulos subjacente que é utilizado para ler e despachar eventos de GUI de plataforma. A implementação do módulo da UI afecta as regras que as aplicações devem seguir ao utilizar módulos Java no seu código.

Despacho de eventos nativos

Subjacente a qualquer aplicação de GUI, seja qual for a sua linguagem ou o seu kit de ferramentas de UI, a plataforma do SO detecta eventos de GUI e coloca-os em filas de eventos de aplicações. Embora a mecânica seja ligeiramente diferente em diferentes plataformas de SO, a base é semelhante. À medida que o utilizador faz clique com o rato, introduz caracteres ou passa por janelas, o SO gera eventos de GUI de aplicações como, por exemplo, cliques de rato, batimentos de teclas ou eventos de pintura de janelas. Determina qual a janela e aplicação que deve receber cada evento e coloca-o na fila de eventos da aplicação.

A estrutura subjacente para qualquer aplicação de GUI com janelas é um ciclo de eventos. As aplicações inicializam-se e depois iniciam um ciclo que lê simplesmente os eventos de GUI na fila e responde em conformidade. O trabalho que for feito ao tratar de um destes eventos deve acontecer rapidamente para manter o sistema da GUI contactável para o utilizador.

As operações longas desencadeadas por eventos de UI devem ser realizadas num módulo separado para permitir que o módulo do ciclo de eventos devolva rapidamente e busque o evento seguinte na fila da aplicação. Todavia, o acesso aos widgets e à API da plataforma a partir de outros módulos deve ser controlado com bloqueio e serialização explícitos. Uma aplicação que não cumpra as regras pode causar falhas numa chamada de SO ou ainda pior, pode bloquear o sistema da GUI por inteiro.

Módulo de UI de SWT

O SWT segue o modelo de módulos suportado directamente pelas plataformas. O programa de aplicação executa o ciclo de eventos no seu módulo principal e despacha eventos directamente a partir do seu módulo. O módulo da UI é aquele onde foi criado o Display. Todos os outros widgets devem ser criados no módulo da UI.

Dado que todo o código de eventos é desencadeado pelo módulo da UI da aplicação, o código da aplicação que tratar eventos pode aceder livremente aos widgets e realizar chamadas de gráficos sem técnicas especiais. No entanto, a aplicação é responsável pela ramificação de módulos de cálculo quando executar operações longas em resposta a um evento.

Nota: O SWT irá desencadear uma SWTException para chamadas efectuadas de um módulo alheio à UI que devam ser feitas do módulo da UI.

O módulo principal, incluindo o ciclo de eventos, para uma aplicação de SWT tem a seguinte estrutura:

   public static void main (String [] args) {
      Display display = new Display ();
      Shell shell = new Shell (display);
      shell.open ();
      // iniciar o ciclo de eventos. Paramos quando o utilizador fizer algo
      // para inutilizar a nossa janela.
      while (!shell.isDisposed ()) {
         if (!display.readAndDispatch ())
            display.sleep ();
      }
      display.dispose ();
   }

Uma vez criados os widgets e a shell (interface) aberta, a aplicação lê e despacha eventos da fila do SO até que a janela da shell seja inutilizada. Se não houver eventos disponíveis para nós na fila, indicamos ao ecrã que entre em estado dormente para dar às outras aplicações ocasião de executar.

O SWT faculta métodos de acesso especial para chamar código de widgets e gráficos de um módulo em segundo plano.

Executar código a partir de um módulo alheio à UI

As aplicações que pretendam chamar código de UI a partir de um módulo alheio à UI devem indicar um Executável que chame o código da UI. Os métodos syncExec(Runnable) e asyncExec(Runnable) na classe Display são utilizados para executar estes executáveis no módulo da UI durante o ciclo de eventos.

A porção de código seguinte demonstra o padrão para utilizar estes métodos:

   // fazer cálculos que resultam em dispêndio de tempo
   ...
   // actualizar agora a UI. Não dependemos do resultado,
   // por isso utilize assíncrono.
   display.asyncExec (new Runnable () {
      public void run () {
         if (!aMinhaJanela.isDisposed())
            aMinhaJanela.redraw ();
      }
   });
   // agora fazer mais cálculos
   ...

É boa prática verificar se o widget foi inutilizado de dentro do executável ao utilizar asyncExec. Dado que podem acontecer outras coisas no módulo da UI entre a chamada de asyncExec e a execução do executável, nunca se tem a certeza do estado em que os widgets estão na altura em que o executável é executado.

A área de trabalho e módulos

As regras de módulos são muito claras quanto à implementação de uma aplicação de SWT de raiz, dado que se controla a criação do ciclo de eventos e a decisão de ramificar módulos de cálculo na nossa aplicação.

Tudo se complica um pouco quando contribuímos com código de plug-in para a área de trabalho. As regras seguintes podem ser consideradas "regras de compromisso" ao utilizar classes de UI de plataforma, embora de edição para edição estas possam constituir excepções a estas regras: