Domanda

Dire che ho un swing GUI, e voglio ascoltare MouseEvents.Chi pensi che dovrebbe essere la classe dell'Ascoltatore, che dovrebbe essere responsabile?Qual è il migliore o il modo preferito per la sua attuazione?Tutte le opinioni?Io di solito in questo modo:

public class MyPanel extends JPanel implements MouseListener{
    private JTable table;
    public void foo(){
         table.addMouseListener(this);
    }
    /* MouseListener */
    //Implement MouseListener here.
}

C'è un modo migliore?


EDIT: Grazie a tutti per la saggezza e la guida.L'ho apprezzato.

È stato utile?

Soluzione

Ci sono alcuni modi comuni di fare i listener di eventi (l'unico che mi viene in mente che ho lasciato nel codice riportato di seguito è statico classi interne).Il codice riportato di seguito utilizza ActionListener poiché è più semplice, ma è possibile applicare l'idea di qualsiasi ascoltatore.

Si noti che il "questo" modo (avendo la classe implementa l'ascoltatore) può portare a un enorme if/else set di istruzioni.Direi che questo è il peggior modo possibile per questo motivo.Non mi piace avere "clearing house" metodi per due motivi:

1) sono grandi 2) si è tentati di fare il lavoro all'interno del metodo anziché ogni if/else chiamare un metodo per fare il lavoro (che, come potete vedere, è quello che ho fatto qui...oops :-)

Anche io non come forma Anonima per due motivi:

1) non si può facilmente ri-utilizzare il codice così si potrebbe scoprire che avete il codice duplicato dopo un po 2) trovo interrompe la lettura del codice (altri non sono d'accordo...gusto personale).Penso che tutti sarebbero d'accordo che se si sta facendo più di 5-10 righe che un anonimo classe interna non è una buona idea (io direi più di 2 è di troppo).

Che lascia l'interno e l'esterno modi.Vorrei utilizzare l'esterno quando sto scrivendo un ascoltatore che non è strettamente legato alla GUI che è in ascolto.Se l'ascoltatore non ha bisogno di informazioni (variabili membro e metodi) che fanno parte della classe (TestFrame in questo caso) vorrei andare per l'esterno classe.Nell'esempio qui sotto ho passato nel "presente" in modo che l'esterno ascoltatori potevano accedere alla GUI...se dovessi scrivere il codice che vorrei invece è una classe interna in quanto richiede qualcosa dalla GUI.

Quindi, il mio ordine di preferenza è:

  • classe interna (statico, se possibile, ma se si sta facendo statico mi piacerebbe andare per la classe esterna)
  • classe esterna
  • anonymous inner class (raro)
  • sono la classe implementa stesso (non posso fare questo.Mai!)

E qui c'è il codice

import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;


public class Main
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(
            new Runnable() 
            {
                public void run() 
                {
                    createAndShowGUI();
                }
            });
    }

    private static void createAndShowGUI()
    {
        final TestFrame frame;

        frame = new TestFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(new Rectangle(10, 10, 300, 300));
        frame.init();
        frame.setVisible(true);
    }
}

class TestFrame
    extends    JFrame
    implements ActionListener
{
    private final JButton aBtn;
    private final JButton bBtn;

    public TestFrame()
    {
        super("Test");

        aBtn = new JButton("A");
        bBtn = new JButton("B");
    }

    public void init()
    {
        setLayout(new FlowLayout());
        add(aBtn);
        add(bBtn);

        // the class, since it implements ActionListener
        aBtn.addActionListener(this);
        bBtn.addActionListener(this);

        // outer classes
        aBtn.addActionListener(new OuterAListener(this));
        bBtn.addActionListener(new OuterBListener(this));

        // inner class
        aBtn.addActionListener(new InnerAListener());
        bBtn.addActionListener(new InnerBListener());

        // anonymous classes
        aBtn.addActionListener(
            new ActionListener()
            {
                public void actionPerformed(final ActionEvent e)
                {
                    System.out.println ("Hi from Anonymous A");
                }
            });

        bBtn.addActionListener(
            new ActionListener()
            {
                public void actionPerformed(final ActionEvent e)
                {
                    System.out.println ("Hi from Anonymous B");
                }
            });
    }

    public void actionPerformed(final ActionEvent evt)
    {
        final Object source;

        source = evt.getSource();

        if(source == aBtn)
        {
            System.out.println ("Hi from this A");
        }
        else if (source == bBtn)
        {
            System.out.println ("Hi from this B");
        }
        else
        {
            // ???
        }
    }

    private class InnerAListener
        implements ActionListener
    {
        public void actionPerformed(final ActionEvent e)
        {
            System.out.println ("Hi from Inner A");
        }
    }

    private class InnerBListener
        implements ActionListener
    {
        public void actionPerformed(final ActionEvent e)
        {
            System.out.println ("Hi from Inner B");
        }
    }
}

class OuterAListener
    implements ActionListener
{
    private final TestFrame frame;

    public OuterAListener(final TestFrame f)
    {
        frame = f;
    }

    public void actionPerformed(final ActionEvent e)
    {
        System.out.println ("Hi from Outer A");
    }
}

class OuterBListener
    implements ActionListener
{
    private final TestFrame frame;

    public OuterBListener(final TestFrame f)
    {
        frame = f;
    }

    public void actionPerformed(final ActionEvent e)
    {
        System.out.println ("Hi from Outer B");
    }
}

Altri suggerimenti

Vorrei suggerire di mettere l'ascoltatore nella sua propria classe, per renderlo riutilizzabile, e di avere una chiara separazione degli interessi

guardare il codice swing di Java. Questo è davvero il posto migliore per vedere buoni standard.

Nel tuo caso, mi piacerebbe avere qualcosa di simile:

public class MyPanel extends JTable {

    public void foo() {
         addMouseListener(new MouseHandler() );
    }

    private class MouseHandler implements MouseListener {
       ...
    }
}

In questo modo si ha chiara separazione di funzionalità. Quando la classe principale inizia attuazione quindici diverse interfacce, il codice diventerà completamente impossibile da mantenere.

classi anonime sono utilizzati principalmente per gli ascoltatori. Se sai che avrai un particolare listener registrato solo una volta ed è piuttosto corto, quindi è possibile utilizzare classe anonima.

Personalmente, mi piace separare la mia GUI dal controller. Quindi vi suggerisco di implementare l'ascoltatore nella classe Controller (ogni GUI funzionale dispone di un proprio) e lavorare lì, anche ha bisogno di utilizzare if...else o swich...case

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