【问题标题】:Images not visible in JList图像在 JList 中不可见
【发布时间】:2017-01-13 17:47:37
【问题描述】:

我正在编写一个小照片应用程序(之前问了一些问题),但我遇到了一个无法解决的问题。这个想法是有两个部分:上一个用于概述(使用缩略图),下一个以全尺寸显示所选图像。我不能使用 ImageIO(我的讲师要求)。

我使用 JList 进行概览,但大多数图像不可见。我选择了一个包含大约 20 张图像的文件夹,但只显示了 2 张。其中一个甚至没有居中。

出于某种原因,如果我删除了这些行:

 thumbnaillist.setFixedCellWidth(thumbW);
 thumbnaillist.setFixedCellHeight(thumbH);

出现了一个以前不可见的图像,但现在其他两个消失了。

这是我的代码:

public class PVE extends JFrame {

    private JFileChooser fileChoose;

    //MenuBar
    private JMenuBar menubar;
    private JMenu file;
    private JMenuItem openFolder;
    private JMenuItem exit;

    //Thumbnails
    private JList thumbnaillist;
    private DefaultListModel<ImageIcon> listmodel;
    private JScrollPane tscroll;
    private ImageIcon thumbs;
    private int thumbW = 100;
    private int thumbH = 100;

    //for full size view
    private JPanel imgview;

    public PVE() {
        setLayout(new BorderLayout());

        //MenuBar
        menubar = new JMenuBar();
        file = new JMenu("File");
        openFolder = new JMenuItem("Open folder...");
        exit = new JMenuItem("Quit");
        file.add(openFolder);
        file.addSeparator();
        file.add(exit);
        menubar.add(file);
        setJMenuBar(menubar);

        fileChoose = new JFileChooser();

        openFolder.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                fileChoose.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                fileChoose.showOpenDialog(null);
                File chosenDir = fileChoose.getSelectedFile();
                loadToThumbView(chosenDir);
            }
        });

        //Thumbnail view
        listmodel = new DefaultListModel();
        thumbnaillist = new JList(listmodel);
        thumbnaillist.setLayoutOrientation(JList.HORIZONTAL_WRAP);
        thumbnaillist.setFixedCellWidth(thumbW);
        thumbnaillist.setFixedCellHeight(thumbH);
        thumbnaillist.setVisibleRowCount(1);
        tscroll = new JScrollPane(thumbnaillist, JScrollPane.VERTICAL_SCROLLBAR_NEVER,
            JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        tscroll.setPreferredSize(new Dimension(0, 100));
        add(tscroll, "North");

        //for full size view
        imgview = new JPanel();
        imgview.setBackground(Color.decode("#f7f7f7"));
        add(imgview, "Center");

        setTitle("Photo Viewer");
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
            SwingUtilities.updateComponentTreeUI(this);
        } catch (Exception e) {

        }

        setSize(700, 700);
        setLocation(200, 200);
        setVisible(true);

    }

    public void loadToThumbView(File folder) {
        listmodel.removeAllElements();
        File[] imgpaths = folder.listFiles();
        for (int j = 0; j < imgpaths.length; j++) {
            listmodel.addElement(resizeToThumbnail(new ImageIcon(imgpaths[j].toString())));
        }
    }

    public ImageIcon resizeToThumbnail(ImageIcon icon) {
        Image img = icon.getImage();
        BufferedImage bf = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
        Graphics g = bf.createGraphics();
        g.drawImage(img, 0, 0, thumbW, thumbH, null);
        ImageIcon kB = new ImageIcon(bf);
        return kB;
    }

    public static void main(String argv[]) {
        PVE pv = new PVE();
    }
}

【问题讨论】:

  • 如果将new ImageIcon(imgpaths[j].toString()) 替换为new ImageIcon(ImageIO.read(imgpaths[j])),会得到不同的结果吗?
  • @VGR OP 在他的问题中说:“我不能使用 ImageIO”

标签: java swing jlist imageicon


【解决方案1】:

您的问题在于您缩放图像的方式。

我不确定为什么,但我猜这与BufferedImage#createGraphics() 调用有关,并且我能够在.png 文件正确绘制时重现.jpg 图像的问题。

但是,如果您缩放图像而不是将它们转换为 BufferedImage 并从中获取新的 ImageIcon,您会得到正确的输出:

public ImageIcon resizeToThumbnail(ImageIcon icon) {
    Image img = icon.getImage();
    Image scaled = img.getScaledInstance(thumbW, thumbH, Image.SCALE_SMOOTH);
    return new ImageIcon(scaled);
}

这是我用来测试的文件夹:

以及您的代码和我的代码的输出:


重要提示

作为建议,如果您使用的只是上面的那个小栏,则不要将窗口设置得那么大。如果您在下面添加其他内容,那没关系,但现在它不是“用户友好”(恕我直言)。而不是JFrame#setSize(),您可以尝试使用JFrame#pack() 方法,以便您的框架调整到它的首选大小。

我在你的程序中注意到的其他一些事情:

  1. 您没有将它放在Event Dispatch Thread (EDT) 中,这很危险,因为您的应用程序不会是线程安全的。如果您更改 main 方法,则可以更改它,如下所示:

    public static void main(String argS[]) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                PVE pv = new PVE();
            }
        });
    }
    
  2. 您正在设置JScrollPane 首选大小,而应覆盖其getPreferredSize() 方法,请参阅Should I avoid the use of setPreferred|Maximum|MinimumSize methods in Java Swing? (YES)

  3. 你正在扩展JFrame,你应该创建它的一个实例,除非你覆盖了它的一个方法(你没有,所以不要这样做)或者你有任何好处这样做的理由。如果您需要扩展Container,则应该扩展JPanel,因为JFrame 是一个刚性容器,不能放在另一个容器中。请参阅this questionthis one

我想我没有遗漏任何东西,希望这会有所帮助

【讨论】:

    【解决方案2】:

    您的“缩放”图像实际上是与原始图像相同大小的图像,但除了左上角绘制的缩放版本之外是空白的。在每个渲染的单元格中,左上角都被剪掉了(至少对于我测试过的有些大的图像)。

    缩放后的图像需要使用缩略图大小创建,而不是原始图像的大小。意思是,改变这个:

    BufferedImage bf = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
    

    到这里:

    BufferedImage bf = new BufferedImage(thumbW, thumbH, BufferedImage.TYPE_INT_ARGB);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多