Что такое хороший способ отображения статуса файла с помощью Swing - PullRequest
0 голосов
/ 12 сентября 2018

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

У меня есть JList, который отображает файлы, которые пользователь добавляет, нажимая кнопку добавления (+), и удаляет файлы, когда пользователь нажимает кнопку удаления (-). С каждым добавленным файлом я хочу ассоциировать значок, который должен указывать состояние файла. Например, если пользователь только добавил файл, а не запустил его (у меня есть еще один JButton для запуска приложения с выбранным файлом), тогда этот значок должен быть красным, а после запуска пользователем этот значок должен изменить цвет на зеленый. , Кроме того, если пользователь удаляет файл, нажимая кнопку (-), он также должен удалить значок, связанный с этим конкретным файлом. Ниже наглядное представление о том, что я хочу.

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

enter image description here

1 Ответ

0 голосов
/ 12 сентября 2018

В программировании данные являются главными.То, как эти данные должны быть представлены, не должно учитываться для данных, это область / ответственность 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, который может отображать информацию, которую выхочу.

Для этого вам нужно начать с чтения Как использовать списки и Написание собственного средства визуализации ячеек

...