Vimos alguns exemplos simples que mostram como dimensionar ou posicionar widgets filho com base no tamanho do pai. Até então, esse tipo de computação ocorria em resposta a um atendente de redimensionamento. Geralmente, essa é a melhor maneira de manipular o posicionamento simples do widget. No entanto, há padrões comuns utilizados pelos aplicativos ao posicionar widgets. Esses padrões podem ser estruturados como algoritmos de layout configuráveis que podem ser reutilizados por muitos aplicativos diferentes.
O SWT define os layouts que fornecem o posicionamento e o dimensionamento gerais dos widgets filho em um composto. Os layouts são classes filha da classe abstrata Layout. Os layouts padrão do SWT podem ser encontrados no pacote org.eclipse.swt.layout.
É preciso compreender algumas definições gerais de redimensionamento e posicionamento de widgets.
Esses conceitos são relevantes para os aplicativos, independentemente do layout utilizado. Você pode pensar em um layout como uma maneira conveniente de compactar a funcionalidade de redimensionamento para reutilização.
Alguns conceitos adicionais são introduzidos pelos layouts.
ConsulteCompreendendo Layouts no SWT para obter outras abordagens e figuras demonstrando esses conceitos.
O snippet de código a seguir mostra o caso simples de um aplicativo utilizando um callback de redimensionamento para dimensionar uma etiqueta de acordo com o tamanho de seu shell pai.
Display display = new Display ();
Shell shell = new Shell (display);
Label label = new Label (shell, SWT.CENTER);
shell.addControlatendente(new ControlAdapter() {
public void controlResized(ControlEvent e) {
label.setBounds (shell.getClientArea ());
}
});
O próximo snippet utiliza um layout para conseguir o mesmo efeito:
Display display = new Display ();
Shell shell = new Shell (display);
Label label = new Label (shell, SWT.CENTER);
shell.setLayout(new FillLayout());
Mesmo neste exemplo simples, a utilização de um layout reduz o código do aplicativo. Em layouts mais complexos, a simplificação é bem maior.
O SWT fornece três classes de layout padrão que podem ser utilizadas em muitas situações.
FillLayout é a classe de layout mais simples. Ela forma o layout de widgets em uma única linha ou coluna, forçando-os a terem o mesmo tamanho. Inicialmente, os widgets terão a mesma altura do widget mais alto e a mesma largura do mais largo. FillLayout não agrupa e não é possível especificar margens ou espaçamento.
Você pode utilizar um FillLayout para formar o layout de botões em uma barra de tarefas ou barra de ferramentas ou para empilhar caixas de entrada em um Grupo. FillLayout pode ser utilizado também quando um Composto possui somente um filho. No exemplo acima, o FillLayout faz com que a etiqueta preencha completamente o shell pai.
RowLayout também forma o layout dos widgets em linhas, mas é mais flexível que o FillLayout. Ele pode agrupar os widgets, criando quantas linhas forem necessárias para exibi-los. Ele também fornece margens configuráveis em cada borda do layout e espaçamento configurável entre os widgets no layout. Você pode compactar um RowLayout, o que forçará todos os widgets a terem o mesmo tamanho. Se você justificar um RowLayout, o espaço extra restante no Composto será alocado como margens entre os widgets.
A altura e a largura entre cada widget em um RowLayout podem ser especificadas em um objeto RowData, o qual deve ser definido no widget utilizando setLayoutData.
GridLayout é o layout mais poderoso (e o mais complexo). GridLayout forma o layout dos widgets em uma grade, fornecendo muitos parâmetros configuráveis que controlam o comportamento das linhas e colunas da grade durante o redimensionamento do composto.
O GridLayout define a API que controla a estratégia geral do layout. O atributo mais importante é o numColumns, o qual determina o tamanho horizontal da grade. Geralmente, esse valor é decidido quando você faz o primeiro design da aparência da janela. A ordem dos widgets na grade é a mesma na qual foram criados. Para alterar a ordem dos widgets na grade, você pode utilizar os métodos de Controle moveAbove(Control) e moveBelow(Control). Esses métodos permitem que os widgets sejam inseridos antes ou depois de outro no layout. (O "acima" e o "abaixo" referem-se à ordenação do widget Z e não à localização na própria grade).
A tabela a seguir resume os parâmetros configuráveis de um GridLayout.
Atributo |
Descrição |
---|---|
horizontalSpacing |
O número de pixels entre a borda direita de uma célula e a borda esquerda de sua célula vizinha. |
makeColumnsEqualWidth |
Especifica se todas as colunas devem ser forçadas a ter a mesma largura. |
marginWidth |
O número de pixels utilizados para a margem das bordas direita e esquerda da grade. |
marginHeight |
O número de pixels utilizados para a margem das bordas superior e inferior da grade. |
numColumns |
O número de colunas que devem ser utilizadas para formar a grade. |
verticalSpacing |
O número de pixels entre a borda inferior de uma célula e a borda superior de sua célula vizinha. |
GridLayout suporta muitos outros parâmetros de layout para cada widget na grade. Essas propriedades estão especificadas no objeto GridData. É preciso definir um GridData como o layoutData de cada widget na grade.
A classe GridData define constantes de estilo que permitem especificar combinações de parâmetros de layout normalmente utilizadas no construtor GridData. Você pode também definir esses atributos individualmente, utilizando os métodos públicos do GridData.
Pode-se conseguir layouts bem mais dinâmicos e complexos utilizando o GridData. Puxar esses valores para widgets diferentes na grade pode produzir muitas combinações diferentes de layouts. Até mesmo os layouts de diálogo mais complexos podem ser especificados utilizando GridData. A capacidade de permitir que os widgets estendam-se pelas células produz muitos layouts que nem sequer parecem uma grade.
A tabela a seguir resume os parâmetros configuráveis para GridData. Consulte Compreendendo Layouts no SWT para obter mais descrições e capturas de tela de exemplo de utilização dos vários parâmetros da grade.
Atributo |
Descrição |
---|---|
grabExcessHorizontalSpace |
Especifica se uma célula deve expandir-se para utilizar o espaço horizontal extra disponível na grade. Depois de os tamanhos da célula na grade serem calculados com base nos widgets e nos dados da grade deles, qualquer espaço extra restante no Composto será alocado para as células que ocupam espaço extra. |
grabExcessVerticalSpace |
Especifica se uma célula deve expandir-se para utilizar o espaço vertical extra disponível na grade. |
heightHint |
Especifica uma altura mínima d widget (e, portanto, da linha que o contém). |
horizontalAlignment |
Pode ser BEGINNING, CENTER, END e FILL. FILL significa que o widget será dimensionado para ocupar a largura toda de sua célula na grade. |
horizontalIndent |
O número de pixels entre o widget e a borda esquerda de sua célula na grade. |
horizontalSpan |
Especifica o número de colunas na grade pelas quais o widget deve expandir-se. Por padrão, um widget ocupa uma célula na grade. Ele pode ocupar células adicionais horizontalmente, através do aumento do seu valor. |
verticalAlignment |
Pode ser BEGINNING, CENTER, END e FILL. FILL significa que o widget será dimensionado para ocupar a altura toda de sua célula na grade. |
verticalSpan |
Especifica o número de linhas na grade pelas quais o widget deve expandir-se. Por padrão, um widget ocupa uma célula na grade. Ele pode ocupar células adicionais verticalmente, através do aumento do seu valor. |
widthHint |
Especifica uma largura mínima para o widget (e, portanto, para a coluna que o contém). |
Ocasionalmente, talvez seja necessário gravar sua própria classe de Layout personalizado. Isso é mais apropriado quando se tem um layout complexo utilizado em muitos lugares diferentes do aplicativo. Talvez seja apropriado quando for possível otimizar o layout utilizando o conhecimento específico do aplicativo. Antes de construir um layout personalizado, considere o seguinte:
A menos que você esteja gravando um layout bastante genérico que será utilizado por vários widgets Compostos, é bem mais simples e mais fácil calcular tamanhos e posicionar filhos em um atendente de redimensionamento. Muitos dos widgets personalizados do SWT foram gravados dessa maneira. Embora um novo widget possa ser implementado como um par Composto/Layout , implementá-lo como um Composto que forma seu layout em um atendente de redimensionamento e computa seu tamanho preferencial no computeSize é mais claro e não envolve a gravação de uma classe extra.
Se você ainda julga necessária uma classe de layout personalizado, é bom primeiro implementar o algoritmo do layout em um atendente de redimensionamento. Isso contribui para simplificar sua própria depuração. Não esqueça de testar os vários casos de layout: redimensionamento menor, maior, agrupamento e recorte. Depois de terminar de trabalhar no algoritmo, o código poderá ser refatorado em uma classe filha do Layout.
Os layouts são os responsáveis pela implementação de dois métodos:
Mais discussões sobre layouts personalizados podem ser encontradas em Compreendendo Layouts no SWT.