图像在JList中不可见

时间:2017-01-13 17:47:38

标签: java swing jlist imageicon

我正在写一个小照片应用程序(之前问过一些问题),我有一个问题,我无法解决。这个想法是有两个部分:上部是概述(使用缩略图),下部是显示所选图像的全尺寸。我不能使用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();
    }
}

2 个答案:

答案 0 :(得分:3)

您的问题是因为您缩放图片的方式。

我不确定原因,但我想这与BufferedImage#createGraphics()电话有关,我可以用.jpg图片重现问题.png文件被正确描绘。

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

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

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

enter image description here

使用您的代码和我的输出:

enter image description here enter image description here

重要说明

并且如果你所有人正在使用的是上面的那个小条,那么建议不要设置一个很大的窗口。如果你在下面添加其他内容,那么它还可以,但是现在它不是那样的,用户友好的&#34; (恕我直言)。您可以尝试使用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?(是)

  3. 您正在扩展JFrame,您应该创建一个它的实例,除非您重写其中一种方法(并且您不是,所以不要&#39}这样做或者你有充分的理由去做。如果您需要扩展Container,则应扩展JPanel,因为JFrame是一个刚性容器,不能放在另一个容器中。请参阅this questionthis one

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

答案 1 :(得分: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);