Dúvida com eventos

Tenho uma duvida, alguem tem um exemplo de como eu poderia adicionar um actionListener fora de uma classe que monta o layout da minha aplicação. Tipo assim, eu tenho um JFrame que tem um botao, e esse botao quando eu clicar nele ele irá fazer algo. Ai vem a duvida, como eu posso adicionar um evento a esse botao fora da classe que monta meu botão no JFrame?

[code]

 public class Tela extends JFrame{
     JButton b;
    
     public Tela(){
      JButton b = new JButton("Faz algo");
      c.add(b);

      }
       public static void main(String args[])
       {
         .....
        }[/code]

}

[code]
public class Eventos implements ActionListener{
Tela t;
public Eventos(){

     t = new Tela();
     /* Daqui pra baixo viria o meu método, por exemplo inserebd, e logo em seguido o evento do meu botão, que faz a ação de inserir no banco.
    */
    }

}[/code]

    Agora como fazer isso, já tentei mas não consegui.

A melhor maneira é trabalhar com Actions.
Em programas pequenos (de teste) é útil fazer com que os objetos ouvintes de eventos sejam this. Mas em produção estender a classe AbstractAction é útil para separar a lógica do sistema da montoeira de código usado para criar a GUI.

Um exemplo:

[code]public class MyAction extends AbstractAction {
public MyAction() {
super("Mensagem", new ImageIcon("balao.gif"));
putValue(SHORT_DESCRIPTION, "Mensagem");
}

  public void actionPerformed(ActionEvent e) {
        JOptionPane.showMessageDialog(null, "Essa é a mensagem");
  }

}[/code]

Tendo a action, agora você faz assim:

[code]MyAction minhaAcao = new MyAction();

JButton b = new JButton(minhaAcao);
JMenuItem m = new JMenuItem(minhaAcao);
[/code]

O interessante agora, é que se você fizer:

minhAcao.setEnabled(false);

Tanto o botão (b) como o item de menu (m) serão desabilitados. Eles se registraram como ouvintes de mudança de estado para o objeto Action que receberam (toda essa funcionalidade está implementada na classe abstrata AbstractAction).

Espero ter ajudado.
Abraços.

Ola,

De uma olhada na classe SwingUtilities. Por exemplo:

public static Accessible getAccessibleChild(Component c, int i) 

Talvez te ajude.

[]'s

Dango, eu não testei o que vc postou ainda, mas acho que é o que preciso, justamente por esse motivo da montoeira de código só pra montar a gui que eu não quero nada alem da gui na classe que monta ela, não quero os eventos, não quero validação de campo, não nada alem de código que monta a tela. Assim acho que já um começo pra poder implementar o padrão MVC em aplicações que utlizam Swing, nesse caso em especifico, eu já estaria separando a camada de view completamente do restante das outras camadas.
E quanto a opção sua mlopes , eu também acho que vou precisar porque é complicado manipular um componente(um botão por exemplo) que não é da classe que faz o papel de controller da minha aplicação.

Nada impede de você acrescentar um método addActionListener a sua classe Tela. Acho que um pouco de código exemplifica melhor. Por generalização vou criar dois botoes, afinal pode ficar difícil de distinguir de forma adequada de qual botão partiu o evento.

public class Tela extends JFrame
{
/** constante para o comando confirma */
public static final String CONFIRMA = "confirma";
/** constante para o comando cancela */
public static final String CANCELA = "cancela";

private JButton confirmaBtn;
private JButton cancelaBtn;

public Tela()
{
     confirmaBtn = new JButton("Confirma");
     confirmaBtn.setActionCommand(CONFIRMA);
     cancelaBtn = new JButton("Cancela");
     cancelaBtn.serActionCommand(CANCELA);
     .....  resto do código
}

public void addActionListener(ActionListener listener)
{
     confirmaBtn.addActionListener(listener);
     cancelaBtn.addActionListener(listener);
}

public void removeActionListener(ActionListener listener)
{
     confirmaBtn.removeActionListener(listener);
     cancelaBtn.removeActionListener(listener);
}

}

Na classe “ActionEvent” existe o método “getActionCommand()” que indica qual o comando. Neste caso vai ser o valor de uma das constantes CONFIRMA ou CANCELA.
Existe também a possibilidade de adicionar mais um parâmetro indicando o comando nos métodos “addActionListener” e “removeActionListener”. Dessa forma o evento seria adicionado apenas ao botão do respectivo comando.
Nenhum código de controle dos botões fica dentro da classe Tela.
Espero que isso resolva o seu problema.

Luiz, to com você!

99% das GUIs que eu faço tem algum tipo de especialização que faz lembrar o MVC: o que é tela não é dado, o que é dado não é tela, e o que é fluxo não é nenhum dos dois.

Pois bem, mas o Swing utiliza MVC em cada componente, isso significa que todo JComponent tem estado, tem código de geração e manipulação de eventos e código para desenhar na tela.

A parte de eventos é baseada na idéia de propriedades que os JavaBeans utilizam, associados a eventos específicos da era AWT. Os botões (e nesse caso estou falando de javax.swing.AbstractButton, por isso pode ser JMenuItem, JCheckBox, JButton, tanto faz) manipulam objetos do tipo Action (javax.swing.Action).

Gerar actions faz parte da filosofia dos botões. Você deveria ouvir, numa gui, eventos para os botões que aparecem nela. Isso facilita, posteriormente, a criação de um menu, ou a alteração do comportamento daquela tela sem mudar o resto, obtendo baixo acoplamento que é importante num desenho OO.

Por exemplo, vc tem um JPanel com um formulário a ser preenchido. O formulário preenchido deve ir para o banco. Como fazer??

  1. Primeiro, tudo o que é persistente devia ter uma classe própria. Então, vamos inventar a classe Projeto, que contém os dados do projeto:
  • JTextField nome;
  • Date dataCriacao;
  • Developer Responsável;
  • String Contratante;
  1. Você delega o salvamento em banco para a outra camada, uma instância da classe (suponha) DatabaseManager:
  • DatabaseManager manager;
  1. Sua GUI tem um botão Salvar e um Cancelar, como é típico:
  • JButton salvar;
  • JButton cancelar;

Normalmente, eu “ouço” os botões no próprio JPanel, pra poder ter código assim:

public void actionPerformed(ActionEvent evt) {
  Object obj = evt.getSource();
  if (obj == salvar) {
    doSalvar();
  }
  else if (obj == cancelar) {
    doCancelar();
  }
}

Isso não te impede de continuar usando o MVC, mas agora em outro nível. Para salvar, vc constrói uma instância de Projeto com os dados do formulário e usa o DatabaseManager pra salvá-lo.

Isso é útil porque se vc muda a classe Projeto, vc não tem que mudar o código de muitas outras classes, mas só onde interessa. Da mesma forma, se em vez de um responsável você quer ter vários, vc pode mudar o seu JComboBox para uma JList sem alterar muita coisa.

O objetivo de um desenho MVC é esse mesmo.

Putz, que mensagem imensa!! : ))

[]s

Ainda não consegui gerar um evento, por exemplo de um botão fora da classe que monta as minhas telas, eu gostaria de ter todos os meus eventos centralizados em uma única classe. Será que alguem pode me ajudar?

Olá a todos!
Luiz, eu tenho uma dúvida que acredito ser semelhante à sua, talvez se eu descrevê-la elucide melhor o que você quis perguntar.
Eu criei uma classe JFrame que instancia várias classes JPanel. Essas classes JPanel, por sua vez, possuem vários JButtons, que gerarão eventos que devem ser disparados através de instâncias da classe Actions (própria para os eventos, e para não se misturar código com GUI) nessa classe JFrame. Os botões dos JPanels chamarão outros JPanel, portanto não pode haver eventos nas classes JPanel (que têm acesso direto ao método addActionListener dos JButtons). Então só se disparariam estes eventos indiretamente, através de outras classes. Colocar os JPanel na classe JFrame é muita porqueira ~0X

Eu pensei em utilizar métodos get e set para cada botão, em cada JPanel, mas não consegui. Os métodos get de cada botão fariam com que um novo botão da classe principal recebesse do JPanel o JButton que deverá gerar o evento. Os set passariam os eventos criados na classe Action para o jbutton do próprio JPanel.
O problema todo é que não estou conseguindo usar o getActionListener, simplesmente pq esse método não existe T=
Não sei como criar um actionListener e depois passá-lo para a criatura da classe JPanel.

Se minha dúvida não corresponde à sua, por favor me diga, pois ainda será uma grande dúvida e devo então criar um tópico para ela…
Obrigado

Não seria recomendável usar uma innerClass?

[code]
public class Tela extends JFrame
{

private JButton confirmaBtn;
private JButton cancelaBtn;

public Tela()
{
confirmaBtn = new JButton(“Confirma”);
cancelaBtn = new JButton(“Cancela”);
confirmaBtn.addActionListener(newActionConfirma());
cancelaBtn.addActionListener(newActionCancela());

  .....  resto do código

}

}

public class ActionConfirma implements ActionListener{

public void actionPerformed(ActionEvent evt)
{
//ação a ser executada
}
}

public class ActionCancela implements ActionListener{

public void actionPerformed(ActionEvent evt)
{
//ação a ser executada
}
}

}[/code]

Luiz, a solução que eu encontrei pra mim pode te ajudar
Eu crio um método set para os eventos de cada componente GUI da classe (no seu caso um JFrame) que irá compor a outra classe.
Dá uma olhada

//JFrame
public void actionBotao(ActionListener a){
   botao.addActionListener(a);
}

que será chamado da sua classe JFrame

...
//classe que utiliza JFrame
JFrame jframe = new JFrame();
frame.actionBotao(
   new ActionListener(){
      public void actionPerformed(ActionEvent e){
          //aqui entra a ação do seu botão
      }
   }
);
...

Espero que tenha ajudado
Forte abraço.

CARAMBA, SÓ DEPOIS DE RESPONDER QUE EU OLHEI A DATA!!!
HUHUAUAHUAHUHUAHUAUAUHUAHHUAHUAHUUHAHUAHUUHAH
me sinto um herói por responder essa dúvida…

Olá pessoal, esse é meu primeiro post aqui no GUJ, não quero apenas ser aproveitador no que eu puder ajudar pode ter certeza que terei o maior prazer,
Bem este tópico é velho, mas é o que mais chegou próximo do que estou tentando fazer… Então estou aqui também voltando no tempo ehehehehe!!

É o seguinte tenho 4 classes…
Uma é a que cria meus botões em um JPanel : botaoSalvar, botaoCancelar, botaoNovo etc…
Outras duas são: Um painel Pessoa Física ou tro Pessoa Jurídica que serão dados update ou repaint para troca de painel segundo um checkBox selecionado;
E por quarto é um InternalFrame que conterá os panels…

Dúvida:
Eu quero padronizar os botões para todas as classes que necessitem dos mesmos botões de operação ou seja …
Poder chamar o sair do InternalFrame com uma instancia do JPanel de botões por exemplo…

Se alguém puder me ajudar fico muito agradecido…

Dica acima serviu, eu que estava criando uma nova instancia aí não néeee ehehehe!!
Valeu!