我正在写一个小照片应用程序(之前问过一些问题),我有一个问题,我无法解决。这个想法是有两个部分:上部是概述(使用缩略图),下部是显示所选图像的全尺寸。我不能使用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();
}
}
答案 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);
}
这是我用来测试的文件夹:
使用您的代码和我的输出:
并且如果你所有人正在使用的是上面的那个小条,那么建议不要设置一个很大的窗口。如果你在下面添加其他内容,那么它还可以,但是现在它不是那样的,用户友好的&#34; (恕我直言)。您可以尝试使用JFrame#setSize()
方法,而不是JFrame#pack()
,因此您的框架会调整其大小的首选大小。
我在你的程序中注意到的其他一些事情:
您没有将它放在Event Dispatch Thread (EDT)内,这是危险的,因为您的应用程序不会以这种方式保持线程安全。如果您按照以下方式更改main
方法,则可以更改:
public static void main(String argS[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
PVE pv = new PVE();
}
});
}
您需要设置JScrollPane
首选尺寸,而应覆盖其getPreferredSize()
方法,请参阅Should I avoid the use of setPreferred|Maximum|MinimumSize methods in Java Swing?(是)
您正在扩展JFrame
,您应该创建一个它的实例,除非您重写其中一种方法(并且您不是,所以不要&#39}这样做或者你有充分的理由去做。如果您需要扩展Container
,则应扩展JPanel
,因为JFrame
是一个刚性容器,不能放在另一个容器中。请参阅this question和this one。
我想我没有遗漏任何东西,希望这有帮助
答案 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);