Как лучше всего отображать статус файла с помощью Swing?

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

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

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

Как лучше всего отображать статус файла с помощью Swing?

«Я думал связать ImageIcon с каждым добавленным файлом» - Ну, давай, остановись. Данные - это король. Пользовательский интерфейс просто представляет данные пользователю таким образом, который, надеюсь, выглядит хорошо. Вместо этого у вас должен быть объект «данные», который имеет ссылку на файл и какой-то статус, который затем можно использовать (возможно, с помощью настраиваемого ListCellRenderer) для отображения состояния. Затем вы можете использовать ListModel для генерации событий «изменения», когда когда-либо состояние менялось, или если вы использовали настраиваемый ListModel, зарегистрируйте слушателя непосредственно в объекте «данные» и попросите его сообщить вам, когда оно изменилось.
MadProgrammer 12.09.2018 11:45

@Arvind Спасибо за предложение! Не могли бы вы уточнить / указать мне пример?

Silver moon 12.09.2018 11:45

@Silvermoon Как пользоваться списками

MadProgrammer 12.09.2018 11:46

@MadProgrammer Спасибо за предложение, но не думаю, что я последую за ним. Я только начал программировать на Java и Swing. Не могли бы вы уточнить?

Silver moon 12.09.2018 11:46

@Stultuske Я знаю о JList, и у меня уже есть графический интерфейс, который добавляет и удаляет файлы. Мне просто было интересно реализовать это в качестве следующего шага

Silver moon 12.09.2018 11:50

@Stultuske Я полностью согласен, но я думал, что хороший способ понять программирование - это реализовать его. Но я полностью согласен с вашим предложением.

Silver moon 12.09.2018 11:52
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
6
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В программировании данные - это король. То, как эти данные представлены, не должно иметь значения для данных, это область / ответственность слоев пользовательского интерфейса / представления.

Часто это модель-представление-контроллер

В вашем примере у вас есть две части (основной) информации. Файл и статус (не запущен, запущен, удален), вы хотите объединить эту информацию как «данные». В 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, который может отображать нужную вам информацию.

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

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