Ao desenvolver um aplicativo Java Swing, o princípio MVC (Model View Controller) às vezes pode ficar confuso. Sem os devidos cuidados e experiência, tudo pode acabar contendo referências a todo o resto e o Controlador corre o risco de ser um Vishnu, onde todo o código é gerenciado centralmente e o Modelo / Controlador se torna um só.
Para manter o padrão MVC claro como cristal e promover um código limpo, alguns princípios devem ser respeitados ao escrever interfaces de usuário. Esta nota reúne alguns desses princípios:
- Freqüentemente, um modelo específico de IU deve ser criado com algum significado visual, mas não é relevante para o back-end. Em termos de design de IU, esse Modelo específico de IU faz parte do modelo e do back-end – portanto, não tente tratá-los de maneira diferente. (por exemplo, um objeto gráfico de rede social, que é um conceito estranho ao banco de dados de backend, mas ainda é um modelo da perspectiva da Visualização).
- A maior parte do Modelo deve ser independente do Controlador. Tanto o modelo quanto o controlador devem ser completamente independentes de qualquer implementação de visualização (consulte a nota 3). Uma boa maneira de garantir isso é mover a Visualização para um projeto separado que depende do Modelo e do Controlador (que pode ser um projeto).
- Faça com que as visualizações sejam ouvintes das mudanças no modelo, registrando-as com o controlador ou modelo (a
@ListenerSupport
anotação do Lombok-pg é ótima para isso). Dessa forma, o controlador não precisa se lembrar de quem precisa ver o quê – as visualizações apenas se registram para o que é relevante para elas. - Ao criar uma interface de Listener, geralmente faz mais sentido receber eventos de mudança atômica. Se View realmente precisa ver o objeto completo também, então talvez valha a pena dar a ele acesso ao Controller (com um getter para o objeto Model relevante) ou uma referência ao objeto (se for final no Controller).
- Não tenha medo de permitir que as assinaturas de View incluam classes de Model: o objetivo não é isolar a View e o Model, mas garantir que o Controller seja responsável por recuperar e alterar o Model. Mas tenha a disciplina de não alterar diretamente o modelo do código de visualização (dê cópias do modelo para a visualização se você for paranóico).
- Tente evitar dar uma referência de Controlador a Visualizações que apenas renderizam informações (ou seja, que não precisam de controle).
- O Controlador não existe para “controlar outros aspectos da IU”, como fazer janelas pop-up – manter a lógica da IU na Visualização.
- O controlador está lá para controlar o modelo. Uma verificação de integridade da API deve revelar muito mais “doSomething” se “addSomethingListener” s em vez de “get / setSomething” s.
- O Java Swing é de encadeamento único, portanto, não se preocupe muito com a segurança do encadeamento na Visualização – use o padrão JavaBean para manter o código limpo (o Lombok facilita isso) em vez de exigir tudo na construção.
- Para evitar referências circulares, uma ordem de instanciação respeitável é:
- criar modelo (pode ser tão simples quanto uma conexão de banco de dados)
- criar controladores
- registrar controladores entre si (eles também podem ser ouvintes)
- registrar o modelo com o controlador
- criar vista
- registrar View as Listener para mudanças no Model / Controller (aplicativos de nível superior podem precisar fazer muitos registros)
- registrar o controlador com visualizações que precisam de controle sobre o modelo
- Use o Editor de GUI do Netbeans para economizar tempo, mas atenha-se aos layouts básicos em vez de layouts modernos projetados para editores de GUI: eles resultam em comportamentos de transparência estranhos e não são verdadeiramente portáteis. O que você deseja geralmente é melhor alcançado com um agregado de JPanels usando layouts apropriados.
- Aprenda as últimas bibliotecas de extensão Swing (por exemplo, SwingX), bem como a biblioteca central.
repaint()
vs : diz ao Swing que uma área da janela está suja; revalidate () diz ao gerenciador de layout para recalcular o layout e deve fazer com que os filhos do painel sejam repintados, mas pode não fazer com que o próprio painel o faça.revalidate()
repaint()
- Não há consenso se um setter deve implicar que o Componente se revalida ou repinta. Tente ser consistente internamente, mas faça o que achar melhor. Algo a ser considerado é que, com o Lombok, ele pode manter o código mais limpo, não personalizando configuradores.
- A maioria dos LayoutManagers ignora completamente os métodos setXXSize, portanto, aprenda quais deles realmente usam esses valores. Sim, isso é realmente uma merda.
- O @BoundSetter do Lombok torna realmente fácil registrar um componente com ele mesmo para receber propertyChange (evento), permitindo ganchos pré / pós para alterações de propriedade. Este é um excelente local para registrar subcomponentes e controladores entre si.