вместо объединенного_pdf gem вы можете использовать pdf-toolkit . он поддерживает шаблоны, объединяет PDF и устанавливает права. Руководство можно найти здесь .
Смотрите на библиотеку Glazed Lists, которая имеет поддержку заметных наборов.
Если бы я должен был сделать это сам, то я, вероятно, создал бы пользовательский интерфейс Listener с elementsAdded, elementsRemoved методы, или подобный :-) (также в зависимости от моих потребностей)
(ПРИМЕЧАНИЕ: Я обновил это сообщение после понимания нескольких моих собственных ошибок, таким образом, это не оригинал, но более усовершенствованный вместо этого),
С этой целью я сделал бы два новых интерфейса, ListListener
и Listenable
и затем я создал бы новый класс как ListenableArrayList
который перенес бы каждый List
метод с вызовом к одному (или больше) соответствующие методы, определенные в ListListener
. В коде это было бы что-то вроде этого:
public class ListenableArrayList<T> extends ArrayList<T>
implements Listenable<T> {
private ArrayList<T> internalList;
private ListListener<T> listener;
/* .. */
public void add(T item) {
listener.beforeAdd(T item);
internalList.add(item);
listener.afterAdd(T item);
}
/* .. */
public void setListener(ListListener<T> listener) {
this.listener = listener;
}
}
public interface ListListener<T> {
/* .. */
void beforeAdd(T item);
void afterAdd(T item);
/* .. */
}
public interface Listenable<T> {
/* .. */
void setListener(ListListener<T> listener);
/* .. */
}
Причина я сделал бы это этот путь, будет состоять в том, чтобы допускать создание действительно специальных слушателей на лету вместо того, чтобы связать ListenableArrayList с некоторой определенной реализацией. Например, с этим следующее было бы возможно:
Listenable<String> list = new ListenableArrayList<String>();
list.setListener(new ListListener<String>() {
@Override
public void beforeAdd(String item) {
System.out.println("About to add element "+item+"...");
}
@Override
public void afterAdd(String item) {
System.out.println("...element "+item+" has been added.");
}
});
Немного нарушенный, возможно, но с другой стороны это допускало бы легкое расширение Наборов, Наборов и этажерки скорее легко.
Можно использовать Заметный Набор: https://commons.apache.org/dormant/events/apidocs/org/apache/commons/events/observable/ObservableCollection.html
Обычно я сделал бы следующее:
public class MyBean {
private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private List<String> names = new ArrayList<String>();
public void addName(String name) {
names.add(name);
pcs.firePropertyChange("names", null, Collections.unmodifiableList(names));
}
public void addPropertyChangeListener(PropertyChangeListener l) {
pcs.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
pcs.removePropertyChangeListener(l);
}
}
PropertyChangeSupport управляет слушателями и запускает события от Вашего имени.
Передающим пустым указателем как "старое значение" это форсирует событие, которое будет запущено. (Вероятно, что слушатели не будут действительно заботиться о старом значении так или иначе),
Вы, возможно, ищете java.beans.PropertyChangeSupport
?
По-моему, необходимо избежать PropertyChangeEvent
. IndexedPropertyChangeEvent
хуже, и очень нечасто используемый Swing так или иначе. Лучше сузить фокус Ваших типов и запустить a javax.swing.event.ChangeEvent
или подобный (даже просто называют a Runnable
).
Для определенных типов (как списки!), Глазурованные Списки (или эквивалентный) упомянутый в другом сообщении Peter Štibraný походят на хороший способ пойти.
Для события GUI колебания я обычно просто использовал бы EventListenerList, чтобы сделать работу для меня.
Править: на перефразировании вопросов: как Вы рассматриваете наборы, я обычно использовал бы событие, подобное типу наборов, таким образом, например, событие TreeModel обычно берет аргумент TreePath, или для чего-то в карте, я указал бы на ключ.
Однако для простого JavaBeans наиболее распространенное, принимают список/массив и просто используют индекс.
Мне кажется, Вам будет нужно fireNamesPropertyAdd
, fireNamesProperyDelete
. Уведомление об уровне списка не будет, по моему скромному мнению, работать, даже если это был массив, и индекс был добавлен, поскольку это не может обработать, удаляет. Если элемент в некотором индексе может быть изменен, Вам также будет нужно fireNamesProperyChange
. Могло бы быть полезно иметь индекс как параметр в дополнение к строковому значению.