Domanda

Attualmente sto lavorando su qualche codice Java che ha un sacco di ActionListeners definite in esso (uno per ogni JButton) e ci sono circa 60 pulsanti. Questi sono tutti definiti come classi interne anonime nel metodo JButton.addActionListener. Ho pensato di modi di refactoring questo per rendere il codice più ordinato guardo come questo sta rendendo sembrava molto disordinato. Ho pensato eventualmente tenendo gli ascoltatori in una classe separata che ha essenzialmente un carico di metodi statici ciascuno di restituire un ascoltatore. Ciò significa che il codice sarà simile a addActionListener(GetActionListener.addActionListener()). Anche se questo modo sarà più ordinato sento che in realtà non è una soluzione elegante. Ho pensato anche una mappa finale statica contenente coppie KV con nome ascoltatore all'ascoltatore stessa. Anche in questo caso tuttavia questo ancora non sembra una soluzione molto elegante. Mi chiedevo se qualcuno avesse qualche idea? Devo anche dire che tutti i actionListeners sono piuttosto differenti.

È stato utile?

Soluzione

Vorrei suggerire di non aggiungere direttamente azioni utilizzando ActionListener. Se fate questo modo diventa non riutilizzabili. Invece avvolgere le azioni in classe javax.swing.Action. In modo che è possibile riutilizzare l'azione dove vuoi. Per es ora è possibile utilizzare la stessa azione per dire un collegamento nel menu di un'azione Copia e il pulsante di copia nella barra degli strumenti. In sostanza l'idea è di non direttamente paio di azioni eseguibili con elementi GUI.

Ora venendo alla tua domanda. Vorrei fare un repository of actions in una classe chiamata, per esempio, con un ActionRepsoitory Action getAction(String) pubblico metodo pubblico. Ogni della vostra azione sarebbe identificato da una costante stringa che si usa per recuperare l'azione dal repository. In genere la stringa sarebbe la actionCommand per l'elemento. Come gestire le azioni nel ActionRepository, attraverso un HasMap o qualsiasi altra cosa, è completamente dipendente da voi.

Questo è come la sua doen in maggior parte del codice proffesional, per quanto ne so.

Altri suggerimenti

Non una duplicazione di questa domanda (che non era un duplicato della domanda ha risposto ... wow), ma la risposta dovrebbe essere applicata.

Se le classi interne stanno facendo più di un semplice chiamare un metodo all'interno della classe esterna, allora si sta facendo "sbagliato" (alla mia definizione di "diritto"). Nel codice postato le chiamate per incrementare () e decremento () sono il modo "giusto" per farlo. Refactoring del codice sono gli ascoltatori inoltrare la chiamata di metodo alla classe esterna è un buon punto di partenza per rendere il codice più gestibile.

Detto questo ... 60 pulsanti su un'interfaccia utente ?! Veramente! Ahia! Sono tutti su un unico schermo o si fa con le schede o qualcosa del genere? (Se si tratta di schede o qualcosa che devo più da offrire nella risposta).

Si potrebbe fare una sottoclasse speciale di ActionListener che utilizza la riflessione per chiamare un determinato nome del metodo, quindi è possibile implementare tutte le 60 azioni come i metodi normali.

package com.example;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MethodAsActionListener implements ActionListener {

    private Object receiver;
    private Method method;

    public MethodAsActionListener(Object receiver, String name) {
        this.receiver = receiver;
        try {
            this.method = receiver.getClass().getDeclaredMethod(name);
        } catch (SecurityException e) {
           throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        try {
            method.invoke(receiver);
        } catch (IllegalArgumentException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

}

e poi se un metodo call alla classe

private call(String name) {
    return new MethodAsActionListener(this, name);
}

quindi è possibile aggiungere le azioni nel modo seguente

button1.addActionListener(call("methodName1"));
button2.addActionListener(call("methodName2"));
button3.addActionListener(call("methodName3"));
button4.addActionListener(call("methodName4"));
button5.addActionListener(call("methodName5"));

se uno di questi metodi è mancante, il programma avrà esito negativo quando l'interfaccia utente è costruita (dato che il metodo di ricerca quando si crea l'ascoltatore azione). Che non è così bello come in fase di compilazione, ma ancora meglio di tutto tardiva quando viene attivato l'azione.

mi sento di raccomandare qualcosa di simile a quello che hai suggerito - creare una singola classe ascoltatore che si sottoscrive tutti gli eventi. Probabilmente si desidera utilizzare una diversa istanza della classe per ogni evento, però, raccontando l'istanza (nel costruttore), in generale, che cosa fare con questo evento specifico.

Il vantaggio di questo è che si può quindi iniziare factoring il codice all'interno del ascoltatori insieme in un minor numero di metodi, perché di solito è abbastanza simile. A volte si può ottenere in un unico metodo.

Un trucco che ho usato per una situazione "Pure spedizione" per la creazione di menu era per specificare il menu, la struttura del menu e il metodo di ogni menu collegamenti voce ai nei dati. Ha bisogno di un po 'di riflessione ma funziona.

In realtà -. Fammi guardare

Si, ho tenuto le classi in un documento Google :) Il dato è stato specificato in questo modo:

final static String[] menus = { "File:*", "Save:save", "Load:load", "(", "Print:-", "Preview:preview", ")", "Quit:quit" };

E 'appena analizzato questo. File diventa un elemento di livello superiore a causa della partenza, salvo chiamerà il metodo "Salva", carico chiamerà il metodo di "Load", stampa è un sotto-menù (da qui il parentesi), con anteprima sotto di essa e la stampa non è vincolata a nulla.

Questa stringa può creare e associare un intero menu con una sola chiamata.

Ecco mio codice sorgente se si vuole giocare con esso.

La classe "TestMenu" nella parte superiore è una classe di test che dimostra come utilizzare il metodo buildMenus.

Ciò è stato fatto un bel po 'di anni fa, avrei potuto farlo in modo diverso ora, ma funziona. Non sono sicuro che mi piace davvero generare il menu, e penso che mi piacerebbe fare il parser stringa di utilizzare una singola stringa, invece di scomponendola in stringhe per ogni elemento - dovrebbe essere facile da garantire che ogni oggetto è in spazi separati. ..

Un API migliore potrebbe essere un metodo bind in questo modo:

bind(this, new JButton("Save"), "save", this);

in cui si preme il pulsante di salvataggio causerebbe il metodo Save per essere chiamato su questo (o qualsiasi altro oggetto che avete passato in). Si potrebbe anche fare il parametro "salvare" opzionale e basta usare il JButton.getText (). Tolower () come il metodo da chiamare se nessun parametro esiste (credo che sia convenzione prima della configurazione)

Non l'ho fatto in questo modo con il menu perché volevo anche di astrarre i rapporti di creazione e menu menu nei miei dati.

Si noti che la codifica in questo modo è un modo fantastico per ottenere la vostra separazione MVC in Java -. Tutto il codice di controllo può essere rimosso dalla visualizzazione

package hEvil;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.border.EmptyBorder;

public class JDial extends JDialog {

private static final long serialVersionUID = -26565050431585019L;
private final JPanel contentPanel = new JPanel();

public static void main(String[] args) {
    try {

        JDial dialog = new JDial();
        dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        dialog.setVisible(true);
        dialog.setTitle("Heavy Evil");
        dialog.setBackground(Color.WHITE);

    } catch (final Exception e) {
        e.printStackTrace();
    }
}

public JDial() {
    setBounds(0, 0, 1300, 800);
    getContentPane().setLayout(new BorderLayout());
    contentPanel.setLayout(new FlowLayout());
    contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
    getContentPane().add(contentPanel, BorderLayout.CENTER);

    JPanel windowPane = new JPanel();
    windowPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
    getContentPane().add(windowPane, BorderLayout.SOUTH);

    {
        JButton cancelButton = new JButton("Exit");
        cancelButton.setActionCommand("Exit");
        windowPane.add(cancelButton);
        cancelButton.setBounds(0, 0, 1200, 700);

    }

    {
        JPanel textPane = new JPanel();
        textPane.setLayout(new FlowLayout(FlowLayout.LEFT));
        getContentPane().add(textPane, BorderLayout.NORTH);
        textPane.setVisible(true);

        {
            JTextArea textArea = new JTextArea("Username", 2, 15);
            textPane.add(textArea);
            textArea.setWrapStyleWord(true);
            textArea.setEditable(true);
            textArea.setFont(Font.getFont(Font.SANS_SERIF));
            textArea.setVisible(true);
            textArea.enableInputMethods(isEnabled());
            textArea.computeVisibleRect(getBounds());
            textArea.setBackground(Color.GRAY);

            JTextArea textArea2 = new JTextArea("Password", 2, 15);
            textPane.add(textArea2);
            textArea2.setWrapStyleWord(true);
            textArea2.setEditable(true);
            textArea2.setFont(Font.getFont(Font.SANS_SERIF));
            textArea2.setVisible(true);
            textArea2.enableInputMethods(isEnabled());
            textArea2.computeVisibleRect(getBounds());
            textArea2.setBackground(Color.GRAY);

        }
        {

            JButton registerButton = new JButton("Register");
            textPane.add(registerButton);

        }
        {
            JButton newButton = new JButton("Submit");
            textPane.add(newButton);
            newButton.setEnabled(true);
            getRootPane().setDefaultButton(newButton);
            newButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent evt) {

                    JFrame newFrame = new JFrame("Welcome");
                    newFrame.setVisible(true);
                    newFrame.setBackground(Color.BLACK);
                    newFrame.setBounds(0, 0, 580, 200);

                    JPanel newPanel = new JPanel();
                    newFrame.add(newPanel);
                    dispose();

                    JButton nuButton = new JButton("Mario");
                    newPanel.add(nuButton);

                    JButton nuButton2 = new JButton("Kirby");
                    newPanel.add(nuButton2);

                    JButton nuButton3 = new JButton("Mew Two");
                    newPanel.add(nuButton3);

                    JButton nuButton4 = new JButton("Vegeta");
                    newPanel.add(nuButton4);

                    JButton nuButton5 = new JButton("Tidus");
                    newPanel.add(nuButton5);

                    JButton nuButton6 = new JButton("Link");
                    newPanel.add(nuButton6);

                    JButton nuButton7 = new JButton("Master Chief");
                    newPanel.add(nuButton7);

                    JButton nuButton8 = new JButton("Snake");
                    newPanel.add(nuButton8);

                    JButton nuButton9 = new JButton("Cash");
                    newPanel.add(nuButton9);

                    JButton nuButton10 = new JButton("Lara");
                    newPanel.add(nuButton10);

                    JButton nuButton11 = new JButton("Max");
                    newPanel.add(nuButton11);

                    JButton nuButton12 = new JButton("Spyro");
                    newPanel.add(nuButton12);

                    JButton nuButton13 = new JButton("Sephiroth");
                    newPanel.add(nuButton13);

                    JButton nuButton14 = new JButton("Scorpion");
                    newPanel.add(nuButton14);

                }
            });

        }

    }

}

}
//AND I WANT TO BE ABLE TO IMPLEMENT EACH BUTTON FROM ANOTHER CLASS
//FROM ACTIONEVENT WITH SOMETHINGS SIMILAR TO nuButtonX.actionImplemented...
//CALLING THE SAME ACTIONLISTENER IF I CAN AND THEN CREATING A CLASS FOR
//MODIFICATIONS AT EACH INSTANCE. 
enter code here
package hEvil;

import java.awt.event.ActionEvent;

import javax.swing.JFrame;

public class ActoEve extends ActionEvent {

/**
 * 
 */
private static final long serialVersionUID = -2354901917888497068L;
public ActoEve(Object arg0, int arg1, String arg2) {
    super(ActionEvent.ACTION_PERFORMED, arg1, "flame_001.jpg");
    // TODO Auto-generated constructor stub
}
public void actionImplemented(ActionEvent evt1) {


    JFrame nuFrame = new JFrame();
    nuFrame.setVisible(true);
    nuFrame.setBounds(0, 0, 300, 200);



    // TODO Auto-generated constructor stub
}

}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top