ouvintes de ação e fontes de eventos em swing
-
16-09-2019 - |
Pergunta
Ok, então se eu adicionar um ActionListener
para um elemento GUI, e é o só Elemento eu uso isso ActionListener
Com, importa qual das seguintes linhas (a, b) eu uso para obter o estado selecionado da caixa de seleção?
final JCheckBox checkbox = (JCheckBox)this.buildResult.get("cbDebugTick");
checkbox.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent event){
boolean bChecked =
// (a) checkbox.isSelected();
// (b) ((JCheckBox)event.getSource()).isSelected();
model.setPrintDebugOn(bChecked);
}
});
Faz sentido para mim que se eu adicionar o ActionListener
Objeta -se a vários elementos da GUI, então devo usar (b).
E em (b), não há problema em lançar cegamente event.getSource()
para JCheckBox
, já que sou eu quem adicionou o ouvinte de ação, ou devo programar defensivamente e fazer um instanceof
Verifica?
Nota: Esta questão está no contexto dos ouvintes do evento em geral; O KDGregory tem alguns pontos positivos abaixo especificamente RE: caixas de seleção que eu havia negligenciado considerar.
Solução
Em (b) para ser rigoroso, você deve realmente fazer uma instância, mas não é tão importante. Eu acho que as duas linhas são boas e aceitáveis, embora (b) seria "melhor código"
Embora, o que geralmente é feito em um ouvinte de ação é simplesmente chamar outro método personalizado para sua caixa de seleção. Então seria algo assim:
@Override public void actionPerformed(ActionEvent event) {
//your treatment would be in this method, where it would be acceptable to use (a)
onCheckBoxActionPerformed(event)
}
Outras dicas
Eu não faria.
Se clicar na caixa de seleção vai iniciar alguma ação, eu anexaria um ItemListener, então basta olhar para o estado de seleção no ItemEvent.
No entanto, as caixas de seleção normalmente não invocam ações, elas gerenciam o estado. Portanto, uma abordagem melhor é examinar todas as suas caixas de seleção em resposta ao que quer que inicie a ação.
EDIT: Alguns comentários sobre as questões maiores que o OP levantou.
Primeiro, é importante perceber que grandes partes do balanço representam a conveniência da implementação, em vez de um modelo de comportamento coerente. Jcheckbox e JButton não tem nada em comum além do fato de que clicar dentro de seu espaço é significativo. No entanto, ambos herdam de ResumoButton, que fornece detalhes de implementação, como o rótulo do botão. Ele também pressupõe que os botões sejam "pressionados" e que pressionar um botão iniciará algum comportamento significativo (a ação). No caso do JCHECKBOX, no entanto, o pressionamento de botões não é importante, a mudança no estado é. Essa mudança de estado é sinalizada para o itemListener - que também é definido no abstratoButton, embora as mudanças de estado não tenham sentido para outros tipos de botões (o Javadoc até diz "Caixa de seleção").
Uma das coisas que o balanço acertou - se difícil de usar - é a ideia disso um Ação é separado do controle que inicia essa ação. Um objeto de ação pode ser chamado de vários controles: um item de menu, um botão em uma caixa de diálogo, um pressionamento de tecla, qualquer que seja. Mais importante do ponto de vista do design é que ele o afasta da idéia de um "ouvinte" genérico que tenta descobrir o que precisa acontecer. Vi aplicativos em que um único ouvinte recebe a entrada de todo o sistema de menus, por exemplo, e depois passa por uma grande cadeia IF/else para descobrir qual item de menu foi pressionado. Usar ações significa que você tem mais classes, mas a longo prazo oferece um aplicativo mais sustentável.
Finalmente, de uma perspectiva de usabilidade, há uma diferença entre os controles que mantêm o estado, como Jcheckbox e Jtextea, e aqueles que iniciam ações, como JButton e Jmenuitem. Eu vi um aplicativo (web) em que clicar em um botão de rádio leva você a uma página diferente. Isso é ruim. Mesmo se você planeja usar os ouvintes internamente, para atualizar o estado de algum modelo, deve se perguntar por que a coleção de elementos da GUI não fornece um modelo.
Para o caso em que o ouvinte é exclusivo (como um ouvinte anon), eu uso (a).
Se o ouvinte será reutilizado (por exemplo, this
é uma instância do ActionListener) Vou escrever como:
@Override
public void actionPerformed(ActionEvent event) {
Object src = event.getSource();
if (src == checkbox) {
boolean bChecked = checkbox.isSelected();
// ...
}
}
Se você tem várias caixas de seleção e elas são processadas da mesma maneira, então instanceof
faz sentido.
Eu programaria com B defensivamente, pois é a opção de melhor prática. Mas se você já usará o código, não há razão para que você não possa fazer um. No entanto, imagine como você ficará feliz com si mesmo se voltar a ele em algum ponto futuro, mude algo e descobrir que você escreveu um bom código que pode reutilizar diretamente ...