A adição de um ActionListener pode ser curta?Posso adicionar argumentos ao actionPerformed?

StackOverflow https://stackoverflow.com/questions/2515552

  •  22-09-2019
  •  | 
  •  

Pergunta

Tenho uma tabela grande contendo um botão em cada célula.Esses botões são muito semelhantes e fazem quase a mesma coisa.Se eu adicionar um ouvinte de ação a cada botão desta forma:

tmp.addActionListener(new ActionListener(){
   @Override
   public void actionPerformed(ActionEvent evt) {
      proposition = proposition + action;
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            updatePropositionPanel();
         }
      });
   }
});

Na verdade, cada ouvinte de ação difere de todos os outros pelo valor do action. proposition e updatePropositionPanel são um campo e um método da classe.

  1. Primeiro pensei que poderia torná-lo mais curto se não usasse classes internas.Então, decidi programar uma nova classe ActionListener.Mas então percebi que neste caso a "proposição" não será visível para as instâncias desta classe.

  2. Então decidi adicionar o método actionPerformed à classe atual e fazer isso: addActionListener(this).Mas então percebi que não sei como dar argumentos ao método actionPerformed.

Então, como isso funciona.Posso adicionar um ouvinte de ação de forma curta e elegante?

ADICIONADO:

Gostei da ideia de programar uma classe interna com um construtor que pode receber alguns argumentos e um método actioPerformed, que pode usar argumentos dados no construtor.Comecei a fazer isso e percebi que isso cria conflitos com outras classes anônimas internas (usadas como no código fornecido acima).Então, acho que vou criar outra classe (não a interna).

Foi útil?

Solução

Você pode criar sua própria classe e passar os dados para o construtor. Por exemplo

public class MyActionListener
{
    private int proposition;
    private MyOtherClass moc;

    public MyActionListener(int proposition, MyOtherClass moc) {
        this.proposition = proposition;
        this.moc = moc;
    }

    public void actionPerformed(ActionEvent evt) {
        proposition += moc.action;
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                moc.updatePropositionPanel();
            }
        });
    }
}

Em seguida, você pode adicioná -lo normalmente, passando quaisquer argumentos que desejar ao construtor:

tmp.addActionListener( new MyActionListener(proposition, this) );

Outras dicas

EDITAR: Eu alterei a classe para mostrar a construção com o MyouterClass.

Aqui estão algum código esboçado. Espero que isso chegue ao seu 1, e é assim que eu o implementaria.

public class MyOuterClass {
    // member variables for MyOuterClass

    public MyOuterClass() {
        // ...constructor stuff here
    }
    // ...outer class stuff here - methods, etc.

    // The code each place you want to add the listener, somewhere in MyOuterClass
    tmp.addActionListener(new MyActionListener(poposition, action));


    // below outer class stuff, although it can really be most places, I usually put
    // it here - personal style preference.  Swing's classes often put inner
    // classes first

    /**
     * An inner class.
     */
    private MyActionListener implements ActionListener {
        /**
      * Object used here as a filler, replace with appropriate
      * class types
      */
        private Object proposition;
        private Object action;

        private MyActionListener(Object proposition, Object action) {
            this.proposition = proposition;
            this.action = action;
        }
        public void actionPerformed(ActionEvent evt) {
          proposition = proposition + action;
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                updatePropositionPanel();
             }
        }
        /**
         * Setters provided in case you need to change proposition and action.  If not,
         * feel free not to have them and to have final members
         */
        private void setProposition(Object proposition) {
            this.proposition = proposition;
        }
        private void setAction(Object action) {
            this.action = action;
        }
    }
}

EDITAR: Para criar outra classe como você solicitou em sua edição, faça o que acima, mas crie uma outra classe não privada em outro arquivo .java e codifique.

Como o único diferente está no valor de action Você pode colocar o código dentro de um método. (Também o @Override é desnecessário e += é útil aqui.)

public void setup(
    final AbstractButton button,
    final int action
) { 
    button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
            proposition += action;
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                   updatePropositionPanel();
                }
           });
        }
    });
}

o invokeLater Provavelmente é inútil, pois você estará no thread de envio de eventos AWT (EDT) de qualquer maneira.

Se você estiver adicionando muitas ações de uso geral, poderá simplificá -lo usando uma interface que não possui um objeto de evento inútil associado a ele.

Se você quisesse ser hackish, poderia adicionar o ouvinte em um construtor de subclasse.

    new ActionHandler(button) { public void action() {
        proposition += action;
        updatePropositionPanel();
    }});

Felizmente, o JDK7 tornará a sintaxe Java para esse tipo de coisa menos detalhada. Java, no entanto, sempre será um pouco detalhado.

A opção 1 funciona se você fizer proposition mutável (por exemplo StringBuilder ao invés de String). A opção 2 funciona se você os declarar final. Dessa forma, eles são acessíveis/visíveis na classe interna.

Você pode criar uma classe MyActionListener separada e passar a proposição e ação dos dois valores com o construtor. Ele declara o código -fonte.

Você poderia criar sua própria classe de ouvinte que implemente ActionListener.Esta classe pode conter variáveis ​​de membro correspondentes aos parâmetros dos quais você está falando;você os configuraria usando o construtor.

A chamada para adicionar o ouvinte seria mais ou menos assim:

tmp.addActionListener(new MyActionListenerSubClass(proposition, action));

Assumirei que suas variáveis ​​de proposição e ação são Strings para fins deste exemplo.Defina uma interface PropositionUpdater, uma interface PropositionPanelUpdater e um detentor de proposta de colaborador:

public interface PropositionUpdater() {
    public void updateProposition(PropositionHolder holder, String action);
}

public interface PropositionHolder() {
    public String getProposition();

    public void setProposition(String proposition);
}

public interface PropositionPanelUpdater() {
    public void updatePropositionPanel();
}

A implementação padrão de um atualizador de proposição é simplesmente esta:

public class DefaultPropositionUpdater implements PropositionUpdater {
    public void updateProposition(final PropositionHolder holder, final String action) {
        holder.setProposition(holder.getProposition() + action);
    }
}

Vou deixar o padrão de PropositionHolder e PropositionPanelUpdater para sua imaginação;)

Agora, aqui está seu ouvinte de ação:

public class PropositionUpdaterActionListener implements ActionListener {
    private PropositionHolder holder;

    private PropositionUpdater updater;

    private PropositionPanelUpdater panelUpdater;

    public PropositionUpdaterActionListener(final PropositionHolder holder, final PropositionUpdater updater, final PropositionPanelUpdater panelUpdater) {
        super();
        this.holder = holder;
        this.updater = updater;
        this.panelUpdater = panelUpdater;
    }

    public void actionPerformed(final ActionEvent evt) {
        //Not sure how you *got* the action, but whatever...
        updater.updateProposition(holder, action);
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                panelUpdater.updatePropositionPanel();
            }
        });
    }
}

Você não disse de quantos botões está falando.

Se é um pequeno número como uma tábua de xadrez ou menos, a abordagem de @juskt é boa.

No entanto, se você olhando para algo maior, eu usaria esta abordagem:

public class MyActionListener {
      public void actionPerformed(ActionEvent evt) {
          JComponent c = (JComponent)evt.getSoource();
          int prop = (Integer)c.getclientProperty("PROPOSITION");
          int act = (Integer)c.getclientProperty("ACTION");
          SomeClass obj = c.getclientProperty("UPDATE");
          prop += act;
          // If necessary, clientPut("PROPOSITION", prop);
          SwingUtilities.invokeLater(new    Runnable() {
              public void run() {
                  obj.updatePropositionPanel();
              }
          });
      }
}

Este ouvinte de ação não possui estado. Como resultado, uma única instância pode ser usada para todos os botões. Para algo como uma placa GO (19x19), isso funciona em 1 objeto em vez de 361.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top