Как мне лучше всего обрабатывать события Swing из нескольких гетерогенных типов компонентов в Java? - PullRequest
0 голосов
/ 06 апреля 2019

Наличие Swing UI с несколькими различными компонентами, которые генерируют интересующие события (например, JButton, JTree, JCheckBox, JTextBox и т. Д.) И зная, что есть по крайней мере 3 способа настроить прослушиватели событий для обработки событий, генерируемых различными элементами управления как и прежде:

  1. каждый компонент получает анонимный класс, который объявляется и создается при вызове addActionListener, и обработка анонимного класса происходит в каждом компоненте

  2. внутренний класс объявлен в том же файле и вызывает экземпляр addActionListener (для каждого элемента управления или для каждого типа элемента управления может быть создан другой внутренний класс), и обработка происходит во внутреннем классе

  3. когда ваш контейнер (JPanel) реализует интерфейс ActionListener и реализует метод actionPerformed и использует getSource, чтобы попытаться идентифицировать вызывающий объект, или использовать getActionCommand, чтобы получить командную строку и использовать ее для различения различных элементов управления и обработки всех типов элементов управления в одном методе actionPerformed (предполагается, что вы используете setActionCommand для каждого компонента, чтобы убедиться, что они не отправляют пустые строки команд)

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

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

Возможно, ответ «нет существенной разницы», и, таким образом, это мнение или личное предпочтение / стиль, но если есть наилучшая практика или техническая причина, по которой тот или иной подход выгоден, я бы хотел понять, что это за соображения.

Если это только мнение, пожалуйста, закройте этот вопрос. Если есть реальные веские причины для дифференциации этих подходов, я хотел бы знать. Обучающие программы часто охватывают то, что возможно, но не когда один из нескольких возможных подходов является оптимальным.

У меня уже есть приложение с JButtons, JTree, JTextAreas, JCheckBox, и у меня есть события, которые генерируются и перехватываются всеми тремя из вышеуказанных подходов (я установил слушатели для каждого). Кажется, они все работают. Неясно, есть ли какая-то причина, по которой та или иная причина более применима в конкретной ситуации или в целом, и если да, то какова причина (причины).

Мой контейнер JPanel имеет несколько типов управления, но я проиллюстрирую три подхода здесь. Это фрагмент, а не полный список.

// this code lives in JPanel container and the container implements
// ActionListener. This first added listener example uses the actionPerformed
// method and all components added listeners like this, that actionPeformed
// would need to use either getSource or getActionCommand from the event to 
// know how to handle the heterogeneous events originating from different 
// controls
specializationCheckBox.addActionListener(this);

// I know this should be a switch or an if else nested as successive
// if statements could be problematic and is inefficient (before
// someone else needs to say so! ;)    
@Override
public void actionPerformed(ActionEvent ae) 
{
        String action = ae.getActionCommand();
        if (action.equals(SUBMIT_BUTTON_TEXT)) {
            // handle submit button event
        }
        if (action.equals(CLEAR_BUTTON_TEXT)) {
            // handle clear button event
        }       
    if (action.equals("SPECIALIZATION_CHECK_BOX"))
    {
        // handle check box event
    }

}  // END OF actionPerformed for various components in the UI   


// this second method uses an inner class (seen below) to handle the 
// events for the Checkbox. In this instance, I could either use one
// such inner class to handle all events from one type of control (e.g. all
// JCheckboxes) or I could use 1 inner class per control or I could 
// use 1 inner class for all events (from differing controls)
specializationCheckBox.addActionListener(new checkBoxHandler());

class checkBoxHandler implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        // handle checkbox action (for single component)
                // could be setup to get all events of one type
                // or instead to get all events of all types
    }
// this third option defines an anonymous class inline and would only
// handle what comes out of this one control. Other controls would have
// to have their own inlined anonymous classes.  
specializationCheckBox.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent ae) 
    {
       // only handles events for THIS component (that one check box) 
    });

Три случая работают и получают события, которые они зарегистрированы для прослушивания.

Что мне неясно, так это то, что при обработке различных событий из разнородных комбинаций компонентов, что является лучшей практикой -

уникальные индивидуальные анонимные классы? (Я сомневаюсь, что это идеально для многих элементов управления),

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

или контейнер направляет все события из всех компонентов в один обработчик actionPeformed для разделения с использованием getSource или getActionCommand?

...