Várias vezes fui criticado por sugerir o uso dos seguintes métodos:
- setPreferredSize
- setMinimumSize
- setMaximumSize
em Swing
componentes. Não vejo alternativa ao uso deles quando quero definir proporções entre os componentes exibidos. Foi-me dito isso:
Nos layouts, a resposta é sempre a mesma: use um LayoutManager adequado
Pesquisei um pouco na web, mas não encontrei nenhuma análise abrangente sobre o assunto. Então, eu tenho as seguintes perguntas:
- Devo evitar completamente o uso desses métodos?
- Os métodos foram definidos por um motivo. Então, quando devo usá-los? Em que contexto? Para que finalidades?
- Quais são exatamente as consequências negativas do uso desses métodos? (Só posso pensar em adicionar portabilidade entre sistemas com resolução de tela diferente).
- Eu não acho que nenhum LayoutManager possa satisfazer exatamente todas as necessidades de layout desejadas. Eu realmente preciso implementar um novo LayoutManager para cada pequena variação no meu layout?
- Se a resposta para 4 for "sim", isso não levará a uma proliferação de classes LayoutManager que serão difíceis de manter?
- Em uma situação em que preciso definir proporções entre filhos de um Componente (por exemplo, filho1 deve usar 10% do espaço, filho2 40%, filho3 50%), é possível conseguir isso sem implementar um LayoutManager personalizado?
fonte
JEditorPane
com HTML que não sugere uma largura. OTOH Não tenho certeza se perdi alguma coisa. Analisarei cuidadosamente as respostas no tópico, mas fiquei interessado se você tiver algum comentário, principalmente no último caso.Algumas heurísticas:
Não use
set[Preferred|Maximum|Minimum]Size()
quando você realmente deseja substituirget[Preferred|Maximum|Minimum]Size()
, como pode ser feito na criação de seu próprio componente, mostrado aqui .Não use
set[Preferred|Maximum|Minimum]Size()
quando puder confiar na substituição cuidadosa de um componentegetPreferred|Maximum|Minimum]Size
, como mostrado aqui e abaixo.Use
set[Preferred|Maximum|Minimum]Size()
para derivar a pós-validate()
geometria, como mostrado abaixo e aqui .Se um componente não tiver um tamanho preferido, por exemplo
JDesktopPane
, talvez seja necessário dimensionar o contêiner, mas qualquer uma dessas opções é arbitrária. Um comentário pode ajudar a esclarecer a intenção.Considere layouts alternativos ou personalizados quando achar que precisaria percorrer muitos componentes para obter tamanhos derivados, conforme mencionado nesses comentários .
fonte
setPreferredSize()
sempre substitui o cálculo do componente por uma escolha arbitrária.Não, não há evidência formal para sugerir que a chamada ou substituição desses métodos não seja permitida. De fato, a Oracle diz que esses métodos são usados para fornecer dicas de tamanho: http://docs.oracle.com/javase/tutorial/uiswing/layout/using.html#sizealignment .
Eles também podem ser substituídos (que é a melhor prática para Swing) ao estender um componente Swing (em vez de chamar o método na instância do componente personalizado)
Mais importante, não importa como você especifique o tamanho do componente, verifique se o contêiner do componente usa um gerenciador de layout que respeita o tamanho solicitado do componente.
Quando você precisar fornecer dicas de tamanho personalizadas ao gerente de Layout dos contêineres, para que o componente seja bem disposto
Muitos gerenciadores de layout não prestam atenção ao tamanho máximo solicitado de um componente. No entanto,
BoxLayout
eSpringLayout
faça. Além disso,GroupLayout
fornece a capacidade de definir explicitamente o tamanho mínimo, preferencial ou máximo, sem tocar no componente.Verifique se você realmente precisa definir o tamanho exato do componente. Cada componente Swing tem um tamanho preferido diferente, dependendo da fonte usada e da aparência. Assim, ter um tamanho definido pode produzir uma aparência variada da interface do usuário em diferentes sistemas
às vezes, problemas podem ser encontrados com
GridBagLayout
campos de texto, nos quais, se o tamanho do contêiner for menor que o tamanho preferido, o tamanho mínimo será usado, o que pode fazer com que os campos de texto diminuam substancialmente.JFrame
não impõe overridengetMinimumSize()
apenas chamandosetMinimumSize(..)
suas obrasSe ao implementar você quer dizer usar, então sim. Ninguém
LayoutManger
pode lidar com tudo, cada umLayoutManager
tem seus prós e contras, portanto, cada um pode ser usado em conjunto para produzir o layout final.Referência:
fonte
setXxxSize
métodos como uma bandeira vermelha que eu sou pode acabar aqui , mesmo quando os documentos sugerem. Eu quase sempre deveria ter substituídogetXxxSize
, onde se tem acesso à geometria necessária; e até pequenos exemplos são reciclados mais do que eu gostaria de pensar. +1 por mencionar a variação entre os gerenciadores de layout e por citar o tutorial.Há muitas respostas boas aqui, mas quero acrescentar um pouco mais sobre os motivos pelos quais você normalmente deve evitá-las (a pergunta surgiu novamente em um tópico duplicado):
Com poucas exceções, se você estiver usando esses métodos, provavelmente estará ajustando sua GUI para ficar bem em uma aparência específica (e com suas configurações específicas do sistema, por exemplo, sua fonte preferida da área de trabalho, etc.). Os métodos em si não são inerentemente ruins, mas as razões típicas para usá-los são . Assim que você começa a ajustar as posições e os tamanhos dos pixels em um layout, corre o risco de a sua GUI quebrar (ou no mínimo parecer ruim) em outras plataformas.
Como exemplo disso, tente alterar a aparência padrão do seu aplicativo. Mesmo apenas com as opções disponíveis na sua plataforma, você pode se surpreender com a baixa qualidade dos resultados.
Portanto, em nome de manter sua GUI funcional e com boa aparência em todas as plataformas (lembre-se, um dos principais benefícios do Java é sua plataforma cruzada), você deve contar com gerenciadores de layout etc. para ajustar automaticamente os tamanhos de seus componentes para que sejam renderizados corretamente fora do seu ambiente de desenvolvimento específico.
Tudo isso dito, você certamente pode conceber situações em que esses métodos são justificados. Novamente, eles não são inerentemente ruins, mas seu uso normalmente é uma grande bandeira vermelha, indicando possíveis problemas na GUI. Apenas verifique se você está ciente do alto potencial de complicações se / quando usá-las e sempre tente e pense se há outra solução de aparência e sensação independente para seus problemas - na maioria das vezes você descobrirá que essas métodos não são necessários.
A propósito, se você se sentir frustrado com os gerenciadores de layout padrão, há muitos bons de terceiros gratuitos e de código aberto, como JGoodies '
FormLayout
ouMigLayout
. Alguns construtores de GUI ainda têm suporte interno para gerenciadores de layout de terceiros - o editor de GUI do WindowBuilder do Eclipse, por exemplo, é fornecido com suporte paraFormLayout
eMigLayout
.fonte
JTextField.setColumns
para definir a contagem de colunas, que ajusta o tamanho preferido de acordo. Se você o fizersetPreferredSize
, estará codificando um tamanho, o que quebrará seus layouts, dependendo do tamanho da fonte da plataforma. Aqui estão alguns campos de texto em um layout de grade,setColumns
chamados apropriadamente . Para seus botões, use layouts apropriados / pesos de grade para controlar os tamanhos.Se você estiver tendo problemas com layouts no Java Swing, recomendo vivamente o JGoodies
FormLayout
fornecido gratuitamente como parte da biblioteca de freeware do Forms por Karsten Lentzsch aqui .Esse gerenciador de layout muito popular é extremamente flexível, permitindo o desenvolvimento de UIs Java muito polidas.
Você encontrará a documentação de Karsten aqui e alguma documentação bastante boa do eclipse aqui .
fonte
Esses métodos são pouco compreendidos pela maioria das pessoas. Você absolutamente não deve ignorar esses métodos. Cabe ao gerente de layout se eles respeitarem esses métodos. Esta página possui uma tabela que mostra quais gerenciadores de layout respeitam quais desses métodos:
http://thebadprogrammer.com/swing-layout-manager-sizing/
Escrevo o código Swing há mais de 8 anos e os gerenciadores de layout incluídos no JDK sempre atenderam às minhas necessidades. Nunca precisei de um gerente de layout de terceiros para obter meus layouts.
Eu direi que você não deve tentar dar dicas ao gerente de layout com esses métodos até ter certeza de que precisa deles. Faça seu layout sem fornecer dicas de dimensionamento (por exemplo, deixe o gerente de layout fazer seu trabalho) e, em seguida, você poderá fazer pequenas correções, se necessário.
fonte
Talvez
GridBagLayout
satisfaça suas necessidades. Além disso, há muitos gerenciadores de layout na Web, e aposto que há um que se adapta às suas necessidades.fonte
Estou vendo de maneira diferente da resposta aceita.
1) Devo evitar completamente o uso desses métodos?
Nunca evite! Eles estão lá para expressar as restrições de tamanho de seus componentes ao gerente de layout. Você pode evitar usá-los se não estiver usando nenhum gerenciador de layout e tentar gerenciar o layout visual por conta própria.
Infelizmente, o Swing não vem com dimensões padrão razoáveis. No entanto, em vez de definir as dimensões de um componente, é melhor OOP descer seu próprio componente com padrões razoáveis. (Nesse caso, você chama setXXX na sua classe descendente.) Como alternativa, você pode substituir os métodos getXXX para o mesmo efeito.
2) Os métodos foram definidos por uma razão. Então, quando devo usá-los? Em que contexto? Para que finalidades?
Sempre. Ao criar um componente, defina seu tamanho mínimo / preferido / máximo realista de acordo com o uso desse componente. Por exemplo, se você possui um JTextField para inserir símbolos de países como o Reino Unido, seu tamanho preferido deve ser tão largo para caber dois caracteres (com a fonte atual etc.), mas provavelmente não faz sentido deixá-lo crescer. Afinal, os símbolos dos países são dois caracteres. Por outro lado, se você tiver um JTextField para inserir, por exemplo, o nome de um cliente, ele pode ter um tamanho preferido, como o tamanho do pixel para 20 caracteres, mas pode aumentar se o layout for redimensionado, então defina o tamanho máximo para mais. Ao mesmo tempo, ter um JTextField de 0px de largura não faz sentido; portanto, defina um tamanho mínimo realista (eu diria que o tamanho de pixel de 2 caracteres).
3) Quais são exatamente as consequências negativas do uso desses métodos?
(Só posso pensar em adicionar portabilidade entre sistemas com resolução de tela diferente).
Sem consequências negativas. Essas são dicas para o gerenciador de layout.
4) Não acho que nenhum LayoutManager possa satisfazer exatamente todas as necessidades de layout desejadas.
Eu realmente preciso implementar um novo LayoutManager para cada pequena variação no meu layout?
Não definitivamente NÃO. A abordagem usual é colocar em cascata diferentes gerenciadores de layout básicos, como layout horizontal e vertical.
Por exemplo, o layout abaixo:
está tendo duas partes. As partes esquerda e direita são um layout horizontal. A parte direita é um JPanel adicionado ao layout horizontal, e este JPanel está tendo um layout vertical que expõe os botões verticalmente.
Obviamente, isso pode se tornar complicado com um layout da vida real. Portanto, os gerenciadores de layout baseados em grade, como o MigLayout, são muito melhores se você estiver prestes a desenvolver algo sério.
5) Se a resposta a 4 for "sim", isso não levará a uma proliferação de classes LayoutManager que se tornarão difíceis de manter?
Não, você definitivamente não deve desenvolver gerenciadores de layout, a menos que precise de algo muito especial.
6) Em uma situação em que preciso definir proporções ...
entre filhos de um componente (por exemplo, filho1 deve usar 10% do espaço, filho2 40%, filho3 50%), é possível conseguir isso sem implementar um LayoutManager personalizado?
Basicamente, depois que os tamanhos preferidos estiverem definidos, talvez você não queira fazer nada em porcentagem. Simplesmente, porque as porcentagens são inúteis (por exemplo, não faz sentido ter um JTextField 10% do tamanho da janela - pois é possível reduzir a janela para que o JTextField fique com 0 px de largura ou pode expandir a janela para que o JTextField fique entre duas exibições em um configuração de vários monitores).
Mas, às vezes você pode usar as porcentagens para controlar tamanhos de blocos maiores de sua GUI (painéis, por exemplo).
Você pode usar o JSplitPane, onde pode predefinir a proporção dos dois lados. Ou você pode usar o MigLayout, que permite definir essas restrições em porcentagem, pixels e outras unidades.
fonte
btnBar.setPreferredSize( dimTouchBtn );
é a melhor maneira de fazer isso. Simples, sem necessidade de gerenciador de layout personalizado. Eu uso principalmenteGridBagLayout
com algunsBorderLayout
eBoxLayout
, aninhando quando conveniente. Esta é uma combinação forte e fácil de usar.Devo evitar completamente o uso desses métodos? Eu não diria "evitá-los". Eu diria que se você acha que precisa deles, provavelmente está fazendo algo errado. Os tamanhos dos componentes são determinados no contexto. Por exemplo, os tamanhos dos componentes de texto são determinados pelo número de linhas e colunas que você especificar, combinado com a fonte que você pode ter escolhido. O tamanho do botão e do rótulo será o tamanho do gráfico, se você definir um, ou o espaço necessário para exibir o texto definido. Cada componente tem um tamanho natural e os gerenciadores de layout os usarão para organizar tudo sem precisar especificar tamanhos. A principal exceção é o JScrollPane, que tem um tamanho independente do que ele contém. Para aqueles, às vezes eu ligo e deixo esse tamanho determinar o tamanho inicial da janela, chamando. Normalmente, deixarei o tamanho da janela determinar o tamanho do JScrollPane. O usuário determinará o tamanho da janela. Muitos gerenciadores de layout ignoram os tamanhos que você define, de modo que geralmente não são muito bons.
setSize()
JFrame.pack()
Os métodos foram definidos por um motivo. Então, quando devo usá-los? Em que contexto? Para que finalidades? Eu acredito que eles foram adicionados para fornecer dicas aos gerentes de layout. Eles podem ter sido escritos por razões históricas, porque os gerentes de layout eram novos e as pessoas não confiavam totalmente neles. Conheço alguns desenvolvedores que evitaram os gerenciadores de layout e colocaram tudo manualmente, apenas porque não queriam se preocupar em aprender um novo paradigma. É uma péssima ideia.
Quais são exatamente as consequências negativas do uso desses métodos? (Só posso pensar em adicionar portabilidade entre sistemas com resolução de tela diferente). Eles são ineficazes e produzem layouts ruins, com objetos sendo espremidos ou esticados para tamanhos não naturais. E os layouts serão quebradiços. Às vezes, alterações no tamanho da janela quebram o layout e colocam as coisas nos lugares errados.
Eu não acho que nenhum LayoutManager possa satisfazer exatamente todas as necessidades de layout desejadas. Eu realmente preciso implementar um novo LayoutManager para cada pequena variação no meu layout? Você não deve "implementar" um novo LayoutManager. Você deve instanciar os existentes. Costumo usar vários gerenciadores de layout em uma única janela. Cada JPanel terá seu próprio gerenciador de layout. Algumas pessoas recusam layouts aninhados, porque são difíceis de manter. Quando os uso, dou a cada um o seu próprio método de criação para facilitar a visualização do que cada um faz. Mas nunca "implemento" um gerenciador de layout. Eu apenas instancia-los.
Se a resposta para 4 for "sim", isso não levará a uma proliferação de classes LayoutManager que serão difíceis de manter? Se você estiver implementando novas classes de gerenciador de layout para pequenas variações no layout, estará usando errado. Se você está apenas implementando novos gerenciadores de layout, provavelmente está fazendo algo errado. A única vez que estendi uma classe LayoutManager, foi adicionar um controle deslizante de zoom a um JScrollPane.
Em uma situação em que preciso definir proporções entre filhos de um Componente (por exemplo, filho1 deve usar 10% do espaço, filho2 40%, filho3 50%), é possível conseguir isso sem implementar um LayoutManager personalizado? O JSplitPane tem uma maneira de especificar a porcentagem que cada componente deve obter. O divisor é móvel por padrão, mas você pode desativá-lo se desejar. Eu não uso muito esse recurso. Normalmente, tenho alguns componentes que ocupam um tamanho definido e o restante do espaço é ocupado por um painel de rolagem. O tamanho do painel de rolagem será ajustado com o tamanho da janela. Se você tiver dois painéis de rolagem lado a lado, poderá colocá-los em um JSplitPane e especificar a porcentagem de novo espaço fornecido a cada um conforme o usuário expande e contrai as janelas.
fonte