Java Swing-Call ActionLisner из внешнего класса

Привет, я новичок в Java Swing.

Есть класс Swing следующим образом:

Class A extends JDialog
{

JButton button=new JButton(" test");
button.addActionListener(new TestAction());

 //Inner class
private class TestAction extends AbstractAction {

        public void actionPerformed(final ActionEvent e) {
            dispose();
        }
    }
}

Приведенный выше код работает хорошо. Необходимо переместить внутренний класс TestAction как обычный файл Java, чтобы его можно было повторно использовать.

public class TestActionNew extends AbstractAction {

    JFrame frame;

    TestActionNew () {
        this.frame = new JFrame();

    }

    public void actionPerformed(final ActionEvent e) {
        frame.dispose();
    }
}

Добавлен новый слушатель для Button button.addActionListener(новый TestActionNew())

Но действие по утилизации не работает. Может кто-нибудь помочь, что я делаю не так здесь. Спасибо

2 ответа

Решение

Вы заботитесь о создании другого кадра и вызове dispose в то время как в качестве вложенного класса, dispose вызывается на включающем экземпляре.

Если вы хотите сделать его многоразовым, вам нужно передать то, на что позвонить dispose в конструктор:

public class TestActionNew extends AbstractAction {

    JFrame frame;

    TestActionNew (JFrame frame) {
        this.frame = frame;

    }

    public void actionPerformed(final ActionEvent e) {
        frame.dispose();
    }
}

Тогда в вашем другом коде используйте:

JButton button = new JButton(" test");
button.addActionListener(new TestAction(this));

Вы могли бы...

Предоставлять ActionListener поддерживать напрямую...

class A extends JDialog {

    JButton button = new JButton(" test");

    public A() {
    }

    public void addActionListener(ActionListener listener) {
        button.addActionListener(listener);
    }

    public void removeActionListener(ActionListener listener) {
        button.removeActionListener(listener);
    }

}

Это имеет тенденцию выставлять элементы (то есть кнопку) другим классам и предполагает, что они знают о внутренних реализациях (т.е. actionCommand) диалога

Вы могли бы...

Обеспечить возможность поставки пользовательских Actions

class A extends JDialog {
    //...
    public void addAction(Action action) {
        JButton btn = new JButton(action);
        buttonPanel.add(btn);
    }
}

Это означает, что диалогу не нужно заботиться "что" Action делает, это просто обеспечивает средство для его выполнения, Action обеспечивает автономную единицу работы, которая должна быть выполнена

Например, учитывая Action лайк...

public class CancelAction extends AbstractAction {

    public CancelAction() {
        putValue(NAME, "Cancel");
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // What ever needs to be done here...
    }

}

Вы бы использовали что-то вроде...

A dialog = A();
dialog.addAction(new CancelAction());

Теперь, очевидно, вы можете настроить действие в соответствии с вашими потребностями, передавая любую информацию Action должен делать свою работу, но диалогу все равно

Вы могли бы...

Создайте предопределенный интерфейс, который определяет действия, которые диалог хочет выполнить...

public interface AListener {
    public void wasCancelled(A dialog);
    public void wasAccepted(A dialog);
}

Затем вы бы прикрепили этот слушатель к экземпляру A и принять соответствующие меры, когда он будет выполнен

class A extends JDialog {
    //...       
    private Set<AListener> listeners = new HashSet<>();

    public void addAListener(AListener listener){
        listeners.add(listener);
    }

    public void removeAListener(AListener listener){
        listeners.add(listener);
    }

    protected void fireWasCancelled() {
        for (AListener listener : listeners) {
            listener.wasCancelled(this);
        }
    }

    protected void fireWasAcceppted() {
        for (AListener listener : listeners) {
            listener.wasAccepted(this);
        }
    }
}

Таким образом, когда в диалоге происходит какое-то "действие" (например, при нажатии кнопки), вы вызываете связанный fireXxx способ уведомить любых зарегистрированных слушателей

A aDialog = new A();
aDialog.addAListener(new AListener() {
    @Override
    public void wasCancelled(A dialog) {
        // Do stuf
    }

    @Override
    public void wasAccepted(A dialog) {
        // Do stuff
    }
});

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

Вы могли бы...

Просто используйте JOptionPane, который предоставляет автономный API для отображения информации пользователю и предоставляет вам обратную связь о том, что пользователь сделал

Что вы должны использовать...?

Вы должны использовать подход или смеси подходов, которые наилучшим образом соответствуют вашим потребностям.

Лично я предпочитаю использовать Action, поскольку это автономная, многократно используемая единица работы, которую можно использовать с кнопками, привязками клавиш и пунктами меню, что делает ее очень гибкой, но если у вас просто есть диалоговое окно с кнопкой "ОК"/"Отмена", возможно, быть немного перебить

Вы могли бы взять вторую идею и просто предоставить функциональность, которая позволяет вам настраивать действия "ok" и "отменять" напрямую, а не гибкость, чтобы указать, какие действия вы когда-либо хотите, например.

Я бы также посоветовал вам взглянуть на раздел "Как использовать действия", так как вы, похоже, еще не полностью осознали всю мощь этого API.

Другие вопросы по тегам