使用Swing

时间:2018-09-12 09:42:14

标签: java swing user-interface jlist imageicon

我想做以下事情,并且我需要一些建议来解决问题,这是最好的方法。

我有一个JList,它显示用户通过单击添加(+)按钮添加的文件,并在用户单击删除(-)按钮时删除文件。对于每个添加的文件,我想关联一个图标,该图标应指示文件的状态。例如,如果用户仅添加文件而未运行文件(我还有另一个JButton用于使用所选文件运行应用程序),则此图标应为红色,并且一旦用户运行它,该图标应更改为绿色。 。另外,如果用户通过单击(-)按钮删除文件,则它也应该删除与该特定文件关联的图标。以下是我想要的图像。

我当时正在考虑将ImageIcon与每个添加的文件相关联,但是我不确定如何更改其外观以显示状态。我也不确定删除文件时如何删除ImageIcon。还有其他方法(ImageIcon除外)吗?任何帮助/建议表示赞赏。

enter image description here

1 个答案:

答案 0 :(得分: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呢?你问,好问题。我们真正想要的是某种方式,可以在任何JList对象的状态更改时通知FileOperation

现在,您可以遍历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