【问题标题】:What is a good way to display status of a file using Swing什么是使用 Swing 显示文件状态的好方法
【发布时间】:2019-02-16 21:55:59
【问题描述】:

我想做以下事情,我需要一些关于什么是最好的方法的建议。

我有一个 JList,它显示用户通过单击添加 (+) 按钮添加的文件,并在用户单击删除 (-) 按钮时删除文件。对于每个添加的文件,我想关联一个应该指示文件状态的图标。例如,如果用户只添加了文件而不运行文件(我有另一个 JButton 用于运行带有所选文件的应用程序),那么这个图标应该是红色的,一旦用户运行它,这个图标应该变成绿色.此外,如果用户通过单击 (-) 按钮删除文件,它也应该删除与该特定文件关联的图标。下面是我想要的图形表示。

我正在考虑将 ImageIcon 与每个添加的文件相关联,但我不确定如何更改其外观以显示状态。我也不确定如何在删除文件时删除 ImageIcon。有没有其他方法(ImageIcon 除外)可以做到这一点?感谢您提供任何帮助/建议。

【问题讨论】:

  • “我正在考虑将 ImageIcon 与每个添加的文件相关联” - 好吧,就到此为止。数据为王。 UI 只是将数据呈现给用户,希望看起来不错。相反,您应该有一个“数据”对象,它具有对文件的引用和某种状态,然后可以使用(可能由自定义ListCellRenderer)来显示状态。然后,您可以使用ListModel 在状态发生更改时生成“更改”事件,或者如果您使用自定义ListModel 直接向“数据”对象注册一个侦听器,并让它在更改时告诉您跨度>
  • @Arvind 谢谢你的建议!你能详细说明/给我举个例子吗?
  • @Silvermoon How to use lists
  • @MadProgrammer 感谢您的建议,但我认为我没有遵循。我刚刚开始 Java 和 Swing 编程。能详细点吗?
  • @Stultuske 我知道 JList 并且已经有了一个可以添加和删除文件的 GUI。我只是想将其作为下一步实施

标签: java swing user-interface jlist imageicon


【解决方案1】:

在编程中,数据为王。数据如何表示不应该是数据考虑的问题,这是 UI/视图层的领域/责任。

这通常由model-view-controller pattern 表示

在您的示例中,您有两条(基本)信息。一个文件和一个状态(未运行、运行、删除),您想将此信息组合为“数据”。在 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 呢?你问,好问题。我们真正想要的是当任何FileOperation 对象的状态发生变化时可以通知JList

现在,您可以迭代ListModel,但这不是一个非常干净的解决方案,更好的解决方案是允许FileOperation 在它发生变化时生成事件,并让ListModel 监听它们并接受它自己的行动。

这是observer patternƒ的基本概念

有很多方法可以做到这一点,但我很懒,所以我只打算使用可用的属性更改 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 来显示您想要的信息。

为此,您必须先阅读How to use listsWriting a Custom Cell Renderer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-19
    • 1970-01-01
    • 2017-12-01
    • 2010-11-20
    • 1970-01-01
    相关资源
    最近更新 更多