В программировании данные являются главными.То, как эти данные должны быть представлены, не должно учитываться для данных, это область / ответственность UI / слоев представления.
Это часто представлено паттерном модель-представление-контроллер
В вашем примере у вас есть две части (основной) информации.Файл и статус (не запущен, запущен, удален), вы хотите объединить эту информацию как «данные».В Java это обычно означает простой старый Java-объект (или Pojo)
Поскольку у статуса есть только ограниченное количество возможностей, мы можем использовать enum
для его представления и, таким образом, ограничивать допустимые значения
public enum FileStatus {
NOT_RUN, RUN, DELETED;
}
И тогда мы можем создать наше собственное pojo ...
public class FileOperation {
private File file;
private FileStatus status;
public FileOperation(File file, FileStatus status) {
this.file = file;
this.status = status;
}
public FileOperation(File file) {
this(file, FileStatus.NOT_RUN);
}
public File getFile() {
return file;
}
public FileStatus getStatus() {
return status;
}
public void setStatus(FileStatus newStatus) {
if (status == newStatus) {
return;
}
this.status = newStatus;
}
}
Теперь, когда мы хотим узнать состояние файла, мы знаем, где его получить.
А как же JList
?Вы спрашиваете, хороший вопрос.Мы действительно хотим, чтобы JList
мог быть проинформирован, когда меняется состояние любого FileOperation
объекта.
Теперь вы можете перебрать ListModel
, но это не очень чистое решение.Лучшее решение - позволить FileOperation
генерировать события при его изменении и ListModel
прослушивать их и предпринимать собственные действия.
Это базовая концепция схемы наблюдателя ƒ
Есть несколько способов сделать это, но я ленив, поэтому я просто собираюсь использовать доступный API изменения свойств
public class FileOperation {
private File file;
private FileStatus status;
private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
public FileOperation(File file, FileStatus status) {
this.file = file;
this.status = status;
}
public FileOperation(File file) {
this(file, FileStatus.NOT_RUN);
}
public File getFile() {
return file;
}
public FileStatus getStatus() {
return status;
}
public void setStatus(FileStatus newStatus) {
if (status == newStatus) {
return;
}
FileStatus oldStatus = status;
status = newStatus;
propertyChangeSupport.firePropertyChange("status", oldStatus, status);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(listener);
}
}
А теперьнам нужен ListModel
, который может ответить на него ...
public class FileOperationListModel extends AbstractListModel<FileOperation> {
private List<FileOperation> items = new ArrayList<FileOperation>(25);
private PropertyChangeListener handler = new PropertyChangeHandler();
public void add(FileOperation fo) {
fo.addPropertyChangeListener(handler);
int size = items.size();
items.add(fo);
fireIntervalAdded(this, size, size);
}
public void remove(FileOperation fo) {
int index = items.indexOf(fo);
if (index < 0) {
return;
}
fo.removePropertyChangeListener(handler);
items.remove(fo);
fireIntervalRemoved(this, index, index);
}
@Override
public int getSize() {
return items.size();
}
@Override
public FileOperation getElementAt(int index) {
return items.get(index);
}
public class PropertyChangeHandler implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (!(evt.getSource() instanceof FileOperation)) {
return;
}
FileOperation fo = (FileOperation) evt.getSource();
int index = items.indexOf(fo);
fireContentsChanged(FileOperationListModel.this, index, index);
}
}
}
Теперь, последний кусок головоломки, вам понадобится пользовательский ListCellRenderer
, который может отображать информацию, которую выхочу.
Для этого вам нужно начать с чтения Как использовать списки и Написание собственного средства визуализации ячеек