web-dev-qa-db-fra.com

Ajouter un auditeur à ArrayList

J'ai un ArrayList auquel j'y ajoute dynamiquement des objets, et un JButton. ArrayList est vide lors de l'exécution de mon programme et le JButton est défini sur setEnabled (false). Je veux activer mon bouton chaque fois qu'il y a 2 éléments dans la liste de tableaux ou plus, et le désactiver à nouveau si la liste de tableaux contient un élément ou est vide. Comment puis-je atteindre cet objectif?

16
Eng.Fouad

ArrayList ne dispose d'aucun mécanisme de notification.

Je vous suggère d'écrire votre propre implémentation List qui délègue à une ArrayList privée pour son stockage, mais ajoute la possibilité d'écouter les notifications ... ou de trouver quelque chose de similaire dans Java même. DefaultListModel peut fonctionne pour vous, bien qu'il n'implémente pas List lui-même.

13
Jon Skeet

Javafx (composant de JRE 8) fournit une implémentation de liste observable. Ce code fonctionne pour moi:

ObservableList<MyAnno> lstAnno1 = FXCollections.observableList(new ArrayList<MyAnno>());

lstAnno1.addListener((ListChangeListener.Change<? extends MyAnno> c) -> {
   c.next();
   updateAnnotation((List<MyAnno>) c.getAddedSubList(), xyPlot);
});

...
lstAnno1.add(new MyAnno(lTs, dValue, strType));
...

public void updateAnnotation(List<MyAnno> lstMyAnno, XYPlot xyPlot) {
   lstMyAnno.forEach(d -> {
   ...
   });
}
14
Michael Baldauf

Comme @Jon Skeet suggère que vous pouvez également faire quelque chose comme:

public class ListResponseModel<E> extends AbstractListModel {

    private static final long serialVersionUID = 1L;

    private ArrayList<E> delegate = new ArrayList<E>();

    @Override
    public int getSize() {
        return delegate.size();
    }

    @Override
    public Object getElementAt(int index) {
        return delegate.get(index);
    }

    public void add(E e){
        int index = delegate.size();
        delegate.add(e);
        fireIntervalAdded(this, index, index);
    }
}
10
Tapas Bose
ObservableList<DynamicObjects> ol = FXCollections.ObservableArrayList(new ArrayList<DynamicObjects>());
ListProperty lp = new SimplePropertyList(ol);

lp.addListener(new ChangeListener(){
        @Override public void changed(ObservableValue o, Object oldVal,
                                      Object newVal){
            if (ol.size() > 1 && !JButton.isEnabled()) {
                JButton.setEnable(true);
            } else if (ol.size < 2 && JButton.isEnabled()) {
                JButton.setEnable(false);
            }
    });
3
jdz

Vous ne pouvez pas faire une telle chose avec ArrayList car, comme le dit @ Jon Skeet, ArrayList ne dispose d'aucun mécanisme de notification. Vous devriez essayer JGoodies qui lie ObservableList qui pourrait vous aider.

Vous pouvez également configurer un minuteur qui vérifiera la taille de ArrayList et modifiera JButton en conséquence. Vous aurez besoin d'un thread pour faire ce travail de liste de suivi à un certain intervalle de temps.

Ou si vous connaissez tout le lieu où vous ajoutez/supprimez des éléments de la liste, écrivez ce login à tout ce lieu.

3
Harry Joy

Si vous écrivez votre propre implémentation List, comme le suggère @Jon Skeet, vous pouvez lui donner un EventListenerList . L'API décrit les méthodes pertinentes.

3
trashgod

En suivant la syntaxe SimpleIntegerProperty, j'ai créé un ArrayList qui se déclenche lorsque la taille change. Dans ce cas, vous devez maintenant définir la taille actuelle de ArrayList, car vous souhaitez réagir lorsque la taille est égale à 2, une solution simple consiste à procéder comme suit:

ArrayListProperty.Java

public class ArrayListProperty<E> extends ArrayList<E> implements ObservableValue<Number> {
    private ExpressionHelper<Number> helper = null;
    private SimpleIntegerProperty sizeProperty;

    public ArrayListProperty(){
        super();
        sizeProperty = new SimpleIntegerProperty(0);
    }

    @Override
    public boolean add(E e) {
        boolean returnValue = super.add(e);
        sizeProperty.set(size());
        fireValueChangedEvent();
        return returnValue;
    }

    @Override
    public void add(int index, E element) {
        super.add(index, element);
        sizeProperty.set(size());
        fireValueChangedEvent();
    }

    @Override
    public E remove(int index) {
        E returnValue = super.remove(index);
        sizeProperty.set(size());
        fireValueChangedEvent();
        return returnValue;
    }

    @Override
    public boolean remove(Object o) {
        boolean returnValue = super.remove(o);
        if(returnValue){
            sizeProperty.set(size());
            fireValueChangedEvent();
        }
        return returnValue;
    }

    protected void fireValueChangedEvent(){
        ExpressionHelper.fireValueChangedEvent(helper);
    }

    @Override
    public void addListener(ChangeListener<? super Number> listener) {
        helper = ExpressionHelper.addListener(helper, sizeProperty, listener);
    }

    @Override
    public void removeListener(ChangeListener<? super Number> listener) {
        helper = ExpressionHelper.removeListener(helper, listener);
    }

    @Override
    public Number getValue() {
        return null;
    }

    @Override
    public void addListener(InvalidationListener listener) {
        helper = ExpressionHelper.addListener(helper, sizeProperty, listener);
    }

    @Override
    public void removeListener(InvalidationListener listener) {
        helper = ExpressionHelper.removeListener(helper, listener);
    }
}

Dans ce cas, l’observable est la taille du tableau, puis, lors de la déclaration de votre liste, vous pouvez ajouter un écouteur et agir lorsque la taille est 2.

ArrayListProperty<Object> arrayList = new ArrayListProperty<>();
arrayList.addListener((ob, ov, nv) -> { 
    if(nv.intValue() == 2) doSomething();
});

Cette implémentation vous permet également d'ajouter une comparaison dans ChangeListener afin de savoir quand quelque chose a été ajouté ou supprimé. Aussi, vous pouvez stocker l'objet ajouté ou supprimé et l'avoir dans l'écouteur.

0
RodMendez

Si vous devez résoudre ce problème en utilisant uniquement Java.util.ArrayList, vous pouvez utiliser la solution ci-dessous. Je ne sais pas si c'est la solution exacte que vous voulez. Mais vous pouvez réaliser votre besoin comme ci-dessous.

Implémenter ce qui devrait arriver après ajouté et supprimé. Personnalisez cette interface selon vos besoins.

public interface ListBehaviorHandler {

    void afterAdded();
    void afterDeleted();
}

Et utilisez la méthode ci-dessous pour obtenir une liste de comportements personnalisée.

public <E> List<E> getCustomList(ListBehaviorHandler listBehaviorHandler) {
        return new ArrayList<E>() {
            @Override
            public boolean add(E e) {
                boolean added = super.add(e);
                listBehaviorHandler.afterAdded();
                return added;
            }

            @Override
            public void add(int index, E element) {
                super.add(index, element);
                listBehaviorHandler.afterAdded();
            }

            @Override
            public E remove(int index) {
                E removed = super.remove(index);
                listBehaviorHandler.afterDeleted();
                return removed;
            }

            @Override
            public boolean remove(Object o) {
                boolean removed = super.remove(o);
                listBehaviorHandler.afterDeleted();
                return removed;
            }
        };
    }
0
Chamly Idunil