Devo evitar o uso dos métodos de tamanho set (Preferred | Maximum | Minimum) Size no Java Swing?

481

Várias vezes fui criticado por sugerir o uso dos seguintes métodos:

  1. setPreferredSize
  2. setMinimumSize
  3. setMaximumSize

em Swingcomponentes. 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:

  1. Devo evitar completamente o uso desses métodos?
  2. Os métodos foram definidos por um motivo. Então, quando devo usá-los? Em que contexto? Para que finalidades?
  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).
  4. 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?
  5. 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?
  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?
Heisenbug
fonte

Respostas:

236
  1. Devo evitar completamente o uso desses métodos?

    Sim para o código do aplicativo.

  2. Os métodos foram definidos por um motivo. Então, quando devo usá-los? Em que contexto? Para que finalidades?

    Eu não sei, pessoalmente, penso nisso como um acidente de design de API. Levemente forçado por componentes compostos com idéias especiais sobre tamanhos de crianças. "Ligeiramente", porque eles deveriam ter implementado suas necessidades com um LayoutManager personalizado.

  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.)

    Algumas razões técnicas (incompletas e infelizmente quebradas devido à migração do SwingLabs para java.net) são, por exemplo, mencionadas nas Regras (hehe) ou no link @bendicott encontrado em seu comentário à minha resposta . Socialmente, colocando muito trabalho em seu colega infeliz que precisa manter o código e localizar um layout quebrado.

  4. 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?

    Sim, existem LayoutManagers poderosos o suficiente para satisfazer uma aproximação muito boa de "todas as necessidades de layout". Os três grandes são JGoodies FormLayout, MigLayout, DesignGridLayout. Portanto, na prática, você raramente escreve LayoutManagers, exceto em ambientes simples e altamente especializados.

  5. 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?

    (A resposta para 4 é "não".)

  6. Em uma situação em que preciso definir proporções entre filhos de um Componente (por exemplo, filho 1 deve usar 10% do espaço, filho 2 40%, filho 3 50%), é possível conseguir isso sem implementar um LayoutManager personalizado?

    Qualquer um dos três grandes pode, nem mesmo o GridBag (nunca se deu ao trabalho de dominar, muitos problemas por falta de energia).

kleopatra
fonte
4
Não tenho certeza absoluta de que concordo com esse conselho em pelo menos duas situações. 1) Componentes renderizados personalizados 2) Usando a JEditorPanecom 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.
Andrew Thompson
2
@Andrew Thompson 1) composições personalizadas: é a própria responsável por retornar dicas úteis de layout, se elas não implantarem buggy 2) até as composições principais são buggy ;-) 3) Não me importo com espaço em branco (embora não tenha sido intencionais desta vez, graças :-)
kleopatra
8
Não acredito que a resposta aceita seja a que diz para evitar o uso dos métodos setXXX (). Às vezes, você simplesmente precisa deles para fornecer uma dica ao gerente de layout. Se você estiver montando um painel, sinta-se à vontade para usar esses métodos quando necessário. Dizendo que acho que, se você usar o gerenciador de layout apropriado, não precisará desses métodos com muita frequência, mas, ocasionalmente, simplesmente precisará deles. Tente colocar um JComboBox ou JSpinner em um X_AXIS BoxLayout e não usá-los, acredite que você precisará setMaximumSize () lá.
Michael
5
@ Michael não, eu absolutamente não precisa dele - a resposta é sempre usar um decente LayoutManager e fazer qualquer multa-ajustes no gerenciador de nível (vs. o nível de componente)
kleopatra
5
Você continua dizendo "use um LayoutManager decente e diga quais tamanhos deseja" em todo o fluxo de pilha, mas nunca fornece exemplos específicos de um LayoutManager "decente". E nenhum dos gerentes padrão permite controlar os tamanhos diretamente.
Ti Strga
100

Algumas heurísticas:

  • Não use set[Preferred|Maximum|Minimum]Size()quando você realmente deseja substituir get[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 componente getPreferred|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 .

insira a descrição da imagem aqui

import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.KeyboardFocusManager;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

/**
 * @see /programming/7229226
 * @see /programming/7228843
 */
public class DesignTest {

    private List<JTextField> list = new ArrayList<JTextField>();
    private JPanel panel = new JPanel();
    private JScrollPane sp = new JScrollPane(panel);

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                DesignTest id = new DesignTest();
                id.create("My Project");
            }
        });
    }

    private void addField(String name) {
        JTextField jtf = new JTextField(16);
        panel.add(new JLabel(name, JLabel.LEFT));
        panel.add(jtf);
        list.add(jtf);
    }

    private void create(String strProjectName) {
        panel.setLayout(new GridLayout(0, 1));
        addField("First Name:");
        addField("Last Name:");
        addField("Address:");
        addField("City:");
        addField("Zip Code:");
        addField("Phone:");
        addField("Email Id:");
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
            .addPropertyChangeListener("permanentFocusOwner",
            new FocusDrivenScroller(panel));
        // Show half the fields
        sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        sp.validate();
        Dimension d = sp.getPreferredSize();
        d.setSize(d.width, d.height / 2);
        sp.setPreferredSize(d);

        JInternalFrame internaFrame = new JInternalFrame();
        internaFrame.add(sp);
        internaFrame.pack();
        internaFrame.setVisible(true);

        JDesktopPane desktopPane = new JDesktopPane();
        desktopPane.add(internaFrame);

        JFrame frmtest = new JFrame();
        frmtest.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frmtest.add(desktopPane);
        frmtest.pack();
        // User's preference should be read from java.util.prefs.Preferences
        frmtest.setSize(400, 300);
        frmtest.setLocationRelativeTo(null);
        frmtest.setVisible(true);
        list.get(0).requestFocusInWindow();
    }

    private static class FocusDrivenScroller implements PropertyChangeListener {

        private JComponent parent;

        public FocusDrivenScroller(JComponent parent) {
            this.parent = parent;
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            Component focused = (Component) evt.getNewValue();
            if (focused != null
                && SwingUtilities.isDescendingFrom(focused, parent)) {
                parent.scrollRectToVisible(focused.getBounds());
            }
        }
    }
}
trashgod
fonte
2
discorde (como você deve ter adivinhado :-) com o raciocínio por "fatores externos": as propriedades XXSize devem expressar apenas as necessidades internas . Ajustar aqueles de fora é mal usado, também conhecido como hacking. Se você quer um quadro (internalização ou J-) com aa tamanho specifc em relação a ele é preferido ... o tamanho do quadro, não o conteúdo
kleopatra
2
@kleopatra: só para ser um pouco insistente: se os métodos setXXSize nunca devem ser usados ​​de fora, por que não foram declarados privados ou protegidos? Não é falta de design? O modificador público não diz implicitamente ao usuário que pode usar esses métodos?
Heisenbug 29/08
2
Eu tenho que concordar com @kleopatra: setPreferredSize()sempre substitui o cálculo do componente por uma escolha arbitrária.
trashgod
1
@trashgod +100 a você eu acho que não há nenhum problema com substituindo estes métodos, mesmo chamando-os (mas é claro que isso significa que você tem um componente personalizado substituindo, assim, seria melhor)
David Kroukamp
5
@DavidKroukamp: Obrigado. Adio à experiência maior de Cleópatra, mas vejo o valor de examinar criticamente a visão contrária.
trashgod
47

Devo evitar completamente o uso desses métodos?

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.

Os métodos foram definidos por um motivo. Então, quando devo usá-los? Em que contexto? Para que finalidades?

Quando você precisar fornecer dicas de tamanho personalizadas ao gerente de Layout dos contêineres, para que o componente seja bem disposto

Quais são exatamente as consequências negativas do uso desses métodos? (Só consigo adicionar portabilidade entre sistemas com resolução de tela diferente).

  • Muitos gerenciadores de layout não prestam atenção ao tamanho máximo solicitado de um componente. No entanto, BoxLayoute SpringLayoutfaça. Além disso, GroupLayoutfornece 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 GridBagLayoutcampos 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.

  • JFramenão impõe overriden getMinimumSize()apenas chamando setMinimumSize(..)suas obras

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 ao implementar você quer dizer usar, então sim. Ninguém LayoutMangerpode lidar com tudo, cada um LayoutManagertem seus prós e contras, portanto, cada um pode ser usado em conjunto para produzir o layout final.

Referência:

David Kroukamp
fonte
3
forneça dicas de tamanho personalizadas que sejam uma contradição em si: fornecer dicas de tamanho (em px!) é a tarefa exclusiva do componente. Ele os calcula com base nos detalhes do estado interno que nenhuma outra parte, exceto ela mesma, pode conhecer (nem pode acompanhar). Do ponto de vista do cliente, os meios de personalização podem ser um LayoutManager adequado e / ou uma API especializada no componente que permite configurar requisitos de tamanho em termos de propriedades relevantes para o tamanho "semânticas", número de linhas / colunas em um componente de texto
kleopatra
3
@kleopatra Eu ainda adoraria saber por que a Oracle nos diz como usar esses métodos e a maneira correta de usá-los. Podemos ter nossas próprias preferências, mas não podemos dizer que os designers não devem usá-lo quando não há evidências para sugerir isso. Mas é por isso que apliquei a recompensa, veja se ela atrairia outras pessoas que pudessem fornecer informações de uma fonte confiável, onde a Oracle declara não usar esses métodos (tornando-se uma má prática se você usa, por exemplo, setMinimumSize deve ser chamado em coisas como JSplitPane etc Isto pode ser visto no tutorial Oráculo de painéis divididos.
David Kroukamp
4
@ David: Eu vim para ver os setXxxSizemétodos como uma bandeira vermelha que eu sou pode acabar aqui , mesmo quando os documentos sugerem. Eu quase sempre deveria ter substituído getXxxSize, 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.
Trashgod 01/10/12
1
D'oh, no meu comentário acima, eu quis citar a resposta aqui .
trashgod
13
+1 "Não, não há evidência formal para sugerir que a chamada ou substituição desses métodos não seja permitida." Spot on. A postagem marcada como resposta é simples BS.
TT.
25

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 ou MigLayout. 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 para FormLayoute MigLayout.

Jason C
fonte
2
Marque com +1 uma resposta atenciosa - apenas discorde de que eles não são inerentemente maus, simplesmente porque são :-) Normalmente, os clientes externos não têm chance alguma de adivinhar - e meras suposições são tão próximas quanto as pessoas de fora podem - dicas de layout na metade do caminho: apenas os próprios componentes têm todas as informações o tempo todo para retornar qualquer coisa útil. E desde o momento em que as pessoas de fora interferem, é sua responsabilidade manter as dicas atualizadas que não podem.
22414 kleopatra
1
Bem, você sabe, eu tenho uma visão mais "armas não matam pessoas, pessoas matam pessoas" desse tipo de coisa. :) Se alguém usa esses métodos, precisa estar ciente de coisas como os pontos positivos que você levanta sobre o uso imprevisível de dicas de layout (e é por isso que as situações em que esses métodos são apropriados são realmente raras).
Jason C #
Eu acho que definir o tamanho preferido não é uma grande bandeira vermelha. Não configurá-lo é uma grande bandeira vermelha. Deixe-me elaborar. O gerenciador de layout - por mais inteligente que seja - não tem idéia da função lógica de um widget da GUI. Por exemplo, o gerenciador de layout não pode distinguir entre um JTextField para inserir CEP e um JTextField para inserir um nome. Da mesma forma, não é possível distinguir entre um botão da ferramenta ao lado de um JTextField ou um grande botão OK na parte inferior de um formulário. Portanto, é necessário um conjunto de widgets melhor ou algumas dicas de dimensionamento, não?
Gee Bee
@ GeeBee Não, esse é um excelente exemplo de bandeira vermelha. O que você deve fazer é usar JTextField.setColumnspara definir a contagem de colunas, que ajusta o tamanho preferido de acordo. Se você o fizer setPreferredSize, 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, setColumnschamados apropriadamente . Para seus botões, use layouts apropriados / pesos de grade para controlar os tamanhos.
Jason C #
@GeeBee E agora, com isso feito corretamente, observe como as larguras dos campos de texto diminuem quando diminuo o tamanho da fonte: i.snag.gy/ZULulh.jpg . Mesmo alterar o tamanho da fonte em tempo real agora funciona automaticamente, em vez de você, digamos, ter que recalcular todas as larguras de campos de texto e chamar explicitamente setPreferredSize novamente para cada um, basta invalidar o layout e seus tamanhos serão ajustados.
Jason C
20

Se você estiver tendo problemas com layouts no Java Swing, recomendo vivamente o JGoodies FormLayoutfornecido 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 .

Tom
fonte
16

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.

Michael
fonte
1
ou há um pequeno equívoco (da sua parte) ou mal-entendido (da minha parte), faça a sua escolha :-) Você continua repetindo (aqui, em seu blog, em sua resposta relacionada ao BoxLayout) o conjunto XXSize como importante - na verdade, o O LayoutManager está (ou não) interessado no XXSize, que é a dica de dimensionamento independente de como surgiu (cálculo interno pelo componente ou forçado manualmente pelo código do aplicativo)
kleopatra
1
Não sei se entendi o que você está recebendo aqui. Mencionei acima que os métodos XXSize () são apenas sugestões. Realmente não vejo nada de errado em dar uma dica ao gerente de layout, se necessário. No meu código swing, você encontrará um método ocasional setXXSize (). Não são muitos, mas de vez em quando eu acho que eles são necessários. JComboBox e JSpinner frequentemente precisam de dicas. Especialmente um JComboBox que é preenchido após sua realização. Você parece ser contra todo e qualquer uso desses métodos e não sei por quê. (talvez eu seja o único que está perdendo o barco nisso, eu acho).
Michael
5
não os métodos são as dicas, as propriedades são: os componentes devem relatar algo razoável para todas as dicas, alguns (como fi JComboBox) não - ao retornar maxInteger ou algo assim. Isso é um bug e deve ser corrigido pelo combo. Quanto ao seu hábito: não se esqueça de ficar longe quando o colega do mantenedor precisar limpá-lo :) Dicas codificadas tendem a destruir o layout com a menor alteração e são difíceis de detectar como o motivo de um layout danificado.
21413 kleopatra
15

Em uma situação em que preciso definir proporções entre filhos de um Componente (filho 1 deve usar 10% do espaço, filho2 40%, filho3 50%), é possível conseguir isso sem implementar um gerenciador de layout personalizado?

Talvez GridBagLayoutsatisfaça suas necessidades. Além disso, há muitos gerenciadores de layout na Web, e aposto que há um que se adapta às suas necessidades.

Thomas
fonte
obrigado pela resposta. Devo assumir que você quis dizer também: "não use setPreferredSize", certo?
Heisenbug 29/08
1
GridBagLayout usa restrições, nas quais você pode especificar o "peso" em X e Y para um determinado componente, para que o LayoutManager possa decidir o que fazer com o espaço extra em um redimensionamento. MAS você ainda precisa / pode usar setPreferredSize para determinar o tamanho preferencial de cada componente, observe que "preferido" não significa que sempre será respeitado. Para casos especiais, você também pode precisar de setMinimumSize e setMaximumSize de qualquer maneira. Eles não são maus , não acredite nisso. docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html
マルちゃんだよ
5

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:

<pre>
+--------------+--------+
| ###JTABLE### | [Add]  | 
| ...data...   |[Remove]|
| ...data...   |        |
| ...data...   |        |
+--------------+--------+
</pre>

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.

Gee Bee
fonte
Mesmo? Isso foi às 0? Isso é melhor do que a resposta aceita que tem mais de 100 ups. Isso basicamente diz "Não usarás setPreferredSize!" o que é terrível. Na minha linha de trabalho, existem muitos requisitos de tamanho específicos, como "Os botões nas telas de toque devem ser [X] por [Y] com espaçamento [M] x [N] entre" requisitos de segurança. btnBar.setPreferredSize( dimTouchBtn );é a melhor maneira de fazer isso. Simples, sem necessidade de gerenciador de layout personalizado. Eu uso principalmente GridBagLayoutcom alguns BorderLayoute BoxLayout, aninhando quando conveniente. Esta é uma combinação forte e fácil de usar.
Loduwijk 9/03/2017
Fiquei apressado no meu comentário acima. Esta foi a primeira resposta que vi depois da resposta aceita. Por que SO não classifica mais por voto conta mais? Eu pensei que essa era uma das principais razões para a contagem de votos originalmente. Ainda mantenho o comentário original; Essa é uma das melhores respostas. Exceto pelo ponto 6 - esse não é tão bom. Existem muitas (a minoria ainda pode ser um grande número) de razões para redimensionar, e o GridBagLayout suporta isso muito bem na maioria dos casos que já tive.
Loduwijk 9/0317
Eu acho que redimensionar vs. não redimensionar não deve ser tratado como uma decisão religiosa. Existem casos de uso em que ninguém deseja redimensionar nada, por exemplo, se você desenvolver uma GUI para um quiosque, com uma resolução fixa predefinida. Se você tem alvos diferentes, como monitores industriais de IHM e o caso de "botões", é necessário ter pelo menos 1 cm por 1 cm para um botão na tela de toque. Nesse caso, o DPI da tela define como você redimensiona. Outras entradas, como campos de texto, não podem ser redimensionadas verticalmente e, às vezes, o redimensionamento horizontal (como um CEP) também não faz sentido.
Gee Bee
0

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.

MiguelMunoz
fonte