Вопрос

Скажи, что у меня есть качающийся графический интерфейс, и я хочу послушать MouseEvents. Анкет Как вы думаете, кто должен быть класс слушателей, кто должен нести ответственность? Какой лучший способ его реализовать? Есть мнения? Я обычно делаю так:

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

Есть ли способ лучше?


РЕДАКТИРОВАТЬ: Спасибо всем за мудрость и помощь. Я ценю это.

Это было полезно?

Решение

Есть несколько распространенных способов сделать слушателей событий (единственные, о которых я могу подумать, что я остановил в коде ниже, - это статические внутренние классы). Приведенный ниже код использует ActionListener, так как он самый простой, но вы можете применить эту идею к любому слушателю.

Обратите внимание, что «этот» способ (реализация класса) может привести к огромному набору операторов, если/иначе. Я бы сказал, что это худший способ из -за этого. Мне не нравится иметь методы «очистки дома» по двум причинам:

1) Они большие 2) Собкачительно выполнять работу внутри метода, а не иметь каждый, если/иначе вызовет метод для выполнения работы (что, как вы можете видеть, это то, что я сделал здесь ... упс: -)

Мне также не нравится анонимный путь по двум причинам:

1) Вы не можете легко повторно использовать код, чтобы вы могли обнаружить, что у вас есть дублированный код через некоторое время 2) Я обнаружил, что он разбивает чтение кода (другие не согласны ... личный вкус). Я думаю, что все согласятся с тем, что если вы делаете более 5-10 строк, анонимный внутренний класс-не очень хорошая идея (я бы сказал, что более 2-это слишком много).

Это оставляет внутренние и внешние способы. Я бы использовал внешний путь, когда пишу слушателя, который не тесно связан с графическим интерфейсом, который он слушает. Если слушатель не нуждается в информации (переменные членов/методы), которые являются частью класса (в данном случае testframe), я бы выбрал внешний класс. В приведенном ниже примере я прошел в «This», чтобы внешние слушатели могли получить доступ к графическому интерфейсу ... если бы я писал код, так, я бы вместо этого сделал его внутренним классом, так как это требует чего -то из графического интерфейса.

Итак, мой заказ предпочтения:

  • Внутренний класс (статический, если это возможно, но если вы делаете его статичным, я бы пошел на внешний класс)
  • Внешний класс
  • анонимный внутренний класс (редко)
  • Попросите класс реализовать это сам (никогда бы я этого не делал. Никогда!)

И вот код

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");
    }
}

Другие советы

Я бы посоветовал поставить слушателя в свой собственный класс, сделать его повторным использованием и иметь четкое разделение проблем

Посмотрите на код качания Java. Это действительно лучшее место, чтобы увидеть хорошие стандарты.

В вашем случае у меня будет что -то вроде:

public class MyPanel extends JTable {

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

    private class MouseHandler implements MouseListener {
       ...
    }
}

Таким образом, у вас есть четкое разделение функциональности. Когда ваш основной класс начнет реализовывать пятнадцать различных интерфейсов, ваш код станет совершенно незаметным.

Анонимные классы в основном используются для слушателей. Если вы знаете, что у вас есть конкретный слушатель, зарегистрированный только один раз, и он довольно короткий, то вы можете использовать анонимный класс.

Лично мне нравится отделить свой графический интерфейс от контроллеров. Поэтому я предложу внедрить слушателя в классе контроллера (каждый функциональный графический интерфейс имеет свои собственные) и работать там, даже необходимо использовать if...else или же swich...case

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top