java - 如何更改JList java中的描述图像

标签 java swing jlist imageicon defaultlistmodel

下面是我在 JList 中显示图像的代码。我想编辑 JList 中显示的每个图像的描述。我不知道该怎么做并且需要帮助。谢谢...

import java.util.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.Serializable;

public class DesignPicture2 {

    private static String imageName;
    static ArrayList<String> imgName = new ArrayList<String>();

    public static void main(String[] args) throws Exception {
        DesignPicture2 mm = new DesignPicture2();
        mm.getImageName("C:\\Images 2 display");

        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        JFrame frame = new JFrame("Image panel");
        frame.setSize(800, 500);
        //frame.setLocationByPlatform(true);
        frame.setLocation(600, 300);

        JList imageList = createImageList();

        frame.getContentPane().add(new JScrollPane(imageList));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    private static JList createImageList() {

        JList imageList = new JList(createModel("C:\\Images 2 display"));
        imageList.setCellRenderer(new ImageCellRenderer());
        imageList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
        imageList.setVisibleRowCount(0);
        imageList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        imageList.setFixedCellWidth(240);
        imageList.setFixedCellHeight(120);

        // imageList.setDragEnabled(false);
        //imageList.setDropMode(DropMode.INSERT);
        imageList.setTransferHandler(new ImageTransferHandler(imageList));

        return imageList;
    }

    private static DefaultListModel createModel(String path) {

        File folder = new File(path);
        File[] listOfFiles = folder.listFiles();
        DefaultListModel model = new DefaultListModel();

        int count = 0;
        for (int i = 0; i < listOfFiles.length - 1; i++) {
            System.out.println("check path: " + listOfFiles[i]);
            imageName = imgName.get(i).toString();
            String name = listOfFiles[i].toString();
            //load only JPEGS

            if (name.endsWith("jpg")) {
                try {
                    ImageIcon ii = new ImageIcon(ImageIO.read(listOfFiles[i]));
                    model.add(count, ii);

                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

        return model;
    }

    static class ImageTransferHandler extends TransferHandler {

        private static final DataFlavor DATA_FLAVOUR = new DataFlavor(ColorIcon.class, "Images");

        private final JList previewList;
        private boolean inDrag;

        ImageTransferHandler(JList previewList) {
            this.previewList = previewList;
        }

        public int getSourceActions(JComponent c) {
            return TransferHandler.MOVE;
        }

        protected Transferable createTransferable(JComponent c) {
            inDrag = true;
            return new Transferable() {
                public DataFlavor[] getTransferDataFlavors() {
                    return new DataFlavor[]{DATA_FLAVOUR};
                }

                public boolean isDataFlavorSupported(DataFlavor flavor) {
                    return flavor.equals(DATA_FLAVOUR);
                }

                public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
                    return previewList.getSelectedValue();
                }
            };
        }

        public boolean canImport(TransferSupport support) {
            if (!inDrag || !support.isDataFlavorSupported(DATA_FLAVOUR)) {
                return false;
            }

            JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
            if (dl.getIndex() == -1) {
                return false;
            } else {
                return true;
            }
        }

        public boolean importData(TransferSupport support) {
            if (!canImport(support)) {
                return false;
            }

            Transferable transferable = support.getTransferable();
            try {
                Object draggedImage = transferable.getTransferData(DATA_FLAVOUR);

                JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
                DefaultListModel model = (DefaultListModel) previewList.getModel();
                int dropIndex = dl.getIndex();
                if (model.indexOf(draggedImage) < dropIndex) {
                    dropIndex--;
                }
                model.removeElement(draggedImage);
                model.add(dropIndex, draggedImage);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }

        protected void exportDone(JComponent source, Transferable data, int action) {
            super.exportDone(source, data, action);
            inDrag = false;
        }
    }

    static class ImageCellRenderer extends JPanel implements ListCellRenderer {

        int count = 0;
        DefaultListCellRenderer defaultListCellRenderer = new DefaultListCellRenderer();
        JLabel imageLabel = new JLabel();
        JLabel descriptionLabel = new JLabel();

        ImageCellRenderer() {
            setLayout(new BorderLayout());
            Border emptyBorder = BorderFactory.createEmptyBorder(5, 5, 5, 5);
            imageLabel.setBorder(emptyBorder);
            descriptionLabel.setBorder(emptyBorder);
            add(imageLabel, BorderLayout.AFTER_LINE_ENDS);
            add(descriptionLabel, BorderLayout.SOUTH);

            // imageLabel.setText(imgName.get(0).toString());
        }

        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            defaultListCellRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            setBorder(defaultListCellRenderer.getBorder());
            setBackground(defaultListCellRenderer.getBackground());
            imageLabel.setIcon((Icon) value);

            if (count > imgName.size() - 1) {
                count = 0;
            } else {
                descriptionLabel.setText(imgName.get(count).toString());

            }
            return this;
        }

    }

    public void getImageName(String path) {
        int c = 0;
        final File dir = new File(path);

        // array of supported extensions (use a List if you prefer)
        final String[] EXTENSIONS = new String[]{
            "jpg", "gif", "png", "bmp" // and other formats you need
        // filter to identify images based on their extensions
        };
        final FilenameFilter IMAGE_FILTER = new FilenameFilter() {

            @Override
            public boolean accept(final File dir, final String name) {
                for (final String ext : EXTENSIONS) {
                    if (name.endsWith("." + ext)) {
                        return (true);
                    }
                }
                return (false);
            }
        };

        if (dir.isDirectory()) { // make sure it's a directory
            for (final File f : dir.listFiles(IMAGE_FILTER)) {
                BufferedImage img = null;
                c++;
                try {
                    img = ImageIO.read(f);

                    // you probably want something more involved here
                    // to display in your UI
                    System.out.println("image: " + f.getName());
                    imgName.add(f.getName().toString());

                } catch (final IOException e) {
                    // handle errors here
                    System.out.println("Error!");
                }
            }
            System.out.println("C: " + c);
        } else {
            System.out.println("Invalid Directory!");
        }
    }

    static class ColorIcon implements Icon, Serializable {

        private Color color;

        ColorIcon(Color color) {
            this.color = color;
        }

        public void paintIcon(Component c, Graphics g, int x, int y) {
            g.setColor(color);
            g.fillRect(x, y, getIconWidth(), getIconHeight());
        }

        public int getIconWidth() {
            return 200;
        }

        public int getIconHeight() {
            return 100;
        }

        public boolean equals(Object o) {
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            return color.equals(((ColorIcon) o).color);
        }
    }

}

当我运行上面的代码时,它以正确的方式显示图像,但是每个图像的描述是固定的,我不知道如何更改它。希望有人能帮助我。

最佳答案

我同意 trashgod(对他的建议 +1),JTable 将是一个更简单的解决方案,原因如下...

JList 不支持可编辑性,因此您需要创建它...

因此,首先,我们需要某种 ListModel 来提供一些额外的功能,特别是在特定索引处设置值的能力...

import javax.swing.ListModel;

public interface MutableListModel<E> extends ListModel<E> {

    public void setElementAt(E value, int index);

    public boolean isCellEditable(int index);

}

接下来,我们需要某种编辑器,在这种情况下,遵循标准的 Swing API 约定,这需要某种基本接口(interface)

import java.awt.Component;
import javax.swing.CellEditor;
import javax.swing.JList;

public interface ListCellEditor<E> extends CellEditor {

    public Component getListCellEditorComponent(
            JList<E> list,
            E value,
            boolean isSelected,
            int index);

    public void applyEditorValue(E value);

}

现在,我们需要为自己创建一个自定义 JList,它能够实际执行编辑单元格值所需的所有功能...

诸如...

  • 识别“开始编辑”事件
  • 判断单元格是否可以编辑
  • 管理编辑过程,准备和展示编辑器,了解编辑器何时停止或取消并适当清理...
  • 在编辑过程中处理选择更改
  • 处理组件焦点变化(我没有做过,因为这本身就很有趣......)

例如……

import java.awt.Component;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JList;
import javax.swing.KeyStroke;
import javax.swing.ListModel;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class EditableList<E> extends JList<E> {

    private ListCellEditor<E> editor;
    private int editingCell = -1;
    private Component editorComponent;

    private CellEditorHandler handler;

    public EditableList(MutableListModel<E> model) {
        this();
        setModel(model);
    }

    public EditableList() {
        InputMap im = getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), "editorCell");

        ActionMap am = getActionMap();
        am.put("editorCell", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Edit baby");
                int cell = getSelectedIndex();
                editCellAt(cell);
            }
        });

        addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                if (isEditing()) {

                    if (!stopCellEditing()) {

                        cancelCellEditing();

                    }

                }
            }
        });
    }

    public boolean isEditing() {

        return editorComponent != null;

    }

    public void cancelCellEditing() {

        getEditor().cancelCellEditing();

    }

    public boolean stopCellEditing() {

        return getEditor().stopCellEditing();

    }

    public CellEditorHandler getCellEditorHandler() {
        if (handler == null) {
            handler = new CellEditorHandler();
        }
        return handler;
    }

    public void setEditor(ListCellEditor<E> value) {
        if (value != editor) {
            ListCellEditor old = editor;
            editor = value;
            firePropertyChange("editor", old, editor);
        }
    }

    public ListCellEditor<E> getEditor() {
        return editor;
    }

    public boolean isCellEditable(int cell) {

        boolean isEditable = false;

        ListModel model = getModel();
        if (model instanceof MutableListModel) {

            MutableListModel mcm = (MutableListModel) model;
            isEditable = mcm.isCellEditable(cell);

        }

        return isEditable;

    }

    protected void editCellAt(int index) {

        if (isCellEditable(index)) {

            ListCellEditor<E> editor = getEditor();
            if (editor != null) {

                Rectangle cellBounds = getCellBounds(index, index);
                E value = getModel().getElementAt(index);
                boolean selected = isSelectedIndex(index);
                editingCell = index;

                editor.addCellEditorListener(getCellEditorHandler());
                editorComponent = editor.getListCellEditorComponent(this, value, selected, index);
                editorComponent.setBounds(cellBounds);

                ensureIndexIsVisible(index);

                add(editorComponent);

                revalidate();

            }

        }

    }

    public int getEditingCell() {
        return editingCell;
    }

    protected void editingHasStopped(ListCellEditor editor) {

        editingCell = -1;

        if (editorComponent != null) {
            remove(editorComponent);
        }

        if (editor != null) {

            editor.removeCellEditorListener(getCellEditorHandler());

        }

    }

    public class CellEditorHandler implements CellEditorListener {

        @Override
        public void editingStopped(ChangeEvent e) {

            E value = getModel().getElementAt(getEditingCell());

            getEditor().applyEditorValue(value);
            ((MutableListModel) getModel()).setElementAt(value, getEditingCell());

            editingHasStopped((ListCellEditor)e.getSource());

        }

        @Override
        public void editingCanceled(ChangeEvent e) {

            editingHasStopped((ListCellEditor)e.getSource());

        }

    }

}

现在,完成所有这些后,您将需要更改构建程序的方式,而不是使用 ListListModel 来管理描述和图像单独地,您可能应该将概念合并到一个单独的、可管理的对象中,例如...

public class ImagePreview {

    private String name;
    private ImageIcon image;

    public ImagePreview(String name, ImageIcon image) {
        this.name = name;
        this.image = image;
    }

    public String getDescription() {
        return name;
    }

    public ImageIcon getImage() {
        return image;
    }

    protected void setDescription(String description) {
        this.name = description;
    }

}

即使您选择使用 JTable,您也会发现它更易于管理...

现在我们需要一些方法来渲染和编辑这些值,为此,我选择从一个可以显示图像和文本的基础组件开始......

public class ImagePreviewPane extends JPanel {

    private JLabel imageLabel = new JLabel();
    private JLabel descriptionLabel = new JLabel();

    public ImagePreviewPane() {
        setLayout(new BorderLayout());
        Border emptyBorder = BorderFactory.createEmptyBorder(5, 5, 5, 5);
        imageLabel.setBorder(emptyBorder);
        descriptionLabel.setBorder(emptyBorder);
        add(imageLabel, BorderLayout.CENTER);
        add(descriptionLabel, BorderLayout.SOUTH);
    }

    protected JLabel getDescriptionLabel() {
        return descriptionLabel;
    }

    protected JLabel getImageLabel() {
        return imageLabel;
    }

    public void setImage(ImageIcon icon) {
        imageLabel.setIcon(icon);
    }

    public void setDescription(String text) {
        descriptionLabel.setText(text);
    }

}

创建一个可以处理编辑的扩展版本...

public static class ImagePreviewEditorPane extends ImagePreviewPane {

    private JTextField editor;

    public ImagePreviewEditorPane() {
        super();
        editor = new JTextField();
        remove(getDescriptionLabel());
        add(editor, BorderLayout.SOUTH);
    }

    @Override
    public void setDescription(String text) {
        editor.setText(text);
    }

    public String getDescription() {
        return editor.getText();
    }

    public void setImagePreview(ImagePreview preview) {
        setImage(preview.getImage());
        setDescription(preview.getDescription());
    }

    @Override
    public void addNotify() {
        super.addNotify();
        editor.requestFocusInWindow();
    }

}

这样做是为了让以后修改组件更容易......

接下来,一个ListCellRenderer

public class ImageCellRenderer extends ImagePreviewPane implements ListCellRenderer {

    public ImageCellRenderer() {
    }

    @Override
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        Color bg = null;
        Color fg = null;

        JList.DropLocation dropLocation = list.getDropLocation();
        if (dropLocation != null
                && !dropLocation.isInsert()
                && dropLocation.getIndex() == index) {

            bg = DefaultLookup.getColor(this, getUI(), "List.dropCellBackground");
            fg = DefaultLookup.getColor(this, getUI(), "List.dropCellForeground");

            isSelected = true;
        }

        if (isSelected) {
            setBackground(bg == null ? list.getSelectionBackground() : bg);
            setForeground(fg == null ? list.getSelectionForeground() : fg);
        } else {
            setBackground(list.getBackground());
            setForeground(list.getForeground());
        }

        if (value instanceof ImagePreview) {
            ImagePreview ip = (ImagePreview) value;
            setImage(ip.getImage());
            setDescription(ip.getDescription());
        } else {
            setImage(null);
            setDescription("??");
        }

        setEnabled(list.isEnabled());
        setFont(list.getFont());

        return this;
    }

}

还有编辑器...

public class ImagePreviewListCellEditor extends AbstactListCellEditor<ImagePreview> {

    private ImagePreviewEditorPane previewPane;

    public ImagePreviewListCellEditor() {
        previewPane = new ImagePreviewEditorPane();
        InputMap im = previewPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "accept");
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancel");

        ActionMap am = previewPane.getActionMap();
        am.put("accept", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                stopCellEditing();
            }
        });
        am.put("cancel", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                cancelCellEditing();
            }
        });
    }

    public void applyEditorValue(ImagePreview preview) {
        preview.setDescription(previewPane.getDescription());
    }

    @Override
    public Component getListCellEditorComponent(JList<ImagePreview> list, ImagePreview value, boolean isSelected, int index) {

        Color bg = null;
        Color fg = null;

        JList.DropLocation dropLocation = list.getDropLocation();
        if (dropLocation != null
                && !dropLocation.isInsert()
                && dropLocation.getIndex() == index) {

            bg = DefaultLookup.getColor(previewPane, previewPane.getUI(), "List.dropCellBackground");
            fg = DefaultLookup.getColor(previewPane, previewPane.getUI(), "List.dropCellForeground");

            isSelected = true;
        }

        if (isSelected) {
            previewPane.setBackground(bg == null ? list.getSelectionBackground() : bg);
            previewPane.setForeground(fg == null ? list.getSelectionForeground() : fg);
        } else {
            previewPane.setBackground(list.getBackground());
            previewPane.setForeground(list.getForeground());
        }

        if (value instanceof ImagePreview) {
            ImagePreview preview = (ImagePreview)value;
            previewPane.setImagePreview(preview);
        } else {
            previewPane.setImagePreview(null);
        }

        return previewPane;
    }

}

最后,把它放在一起......

EditableList

public class DesignPicture2 {

    public static void main(String[] args) throws Exception {

        DesignPicture2 mm = new DesignPicture2();

        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        JFrame frame = new JFrame("Image panel");
        frame.setSize(800, 500);
        frame.setLocation(600, 300);

        JList imageList = createImageList();

        frame.getContentPane().add(new JScrollPane(imageList));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    private static JList createImageList() {

        EditableList<ImagePreview> imageList = new EditableList(createModel("..."));
        imageList.setEditor(new ImagePreviewListCellEditor());
        imageList.setCellRenderer(new ImageCellRenderer());
        imageList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
        imageList.setVisibleRowCount(0);
        imageList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        imageList.setFixedCellWidth(240);
        imageList.setFixedCellHeight(120);

        return imageList;
    }

    private static MutableListModel<ImagePreview> createModel(String path) {

        File folder = new File(path);
        File[] listOfFiles = folder.listFiles();
        DefaultMutableListModel<ImagePreview> model = new DefaultMutableListModel<>();

        int count = 0;
        for (int i = 0; i < listOfFiles.length - 1; i++) {
            System.out.println("check path: " + listOfFiles[i]);
            String name = listOfFiles[i].toString();

            if (name.endsWith("jpg")) {
                try {
                    ImageIcon ii = new ImageIcon(ImageIO.read(listOfFiles[i]));
                    model.addElement(new ImagePreview(name, ii));

                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

        return model;
    }
}

关于java - 如何更改JList java中的描述图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23796471/

相关文章:

java - 如何停止匿名类中的 Swing 计时器?

java - 从 JTable 到直方图 - Swing

java - 当有更多选项卡时,如何将 VerticalScrollPane 设置为仅 JtabbedPane 中的选项卡?

java - 如果语句和 Swing 没有按预期工作,如何让 EDT 进入休眠状态?

java - 如何在 Swing 中使用图像 slider ?

java - TestUI.java 使用未经检查或不安全的操作。注: Recompile with -Xlint:unchecked for details

Java 等待/通知

java - Hibernate 与 HSQLDB 和 Oracle

java - 无法使用 Genymotion 运行我的应用程序

java - Swing 。用 JList 填充 JScrollPane