图像在 JList 中不可见
Images not visible in JList
我正在写一个小照片应用程序(之前问过一些问题),但我有一个问题无法解决。这个想法是有两个部分:上面的部分用于概述(使用缩略图),下面的部分以全尺寸显示所选图像。我不能使用 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();
}
}
您的问题是因为您缩放图像的方式。
我不确定为什么,但我想这与 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);
}
这是我用来测试的文件夹:
你的代码和我的代码的输出:
重要提示
作为建议,如果您使用的只是上面那个小栏,则不要将 window 设置得那么大。如果您要在下面添加其他内容,那没关系,但现在还不是 "user friendly"(恕我直言)。而不是 JFrame#setSize()
you could try using 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
,您应该改为创建它的一个实例,除非您要覆盖它的其中一个方法(而您没有,所以不要这样做) 或者您有充分的理由这样做。如果您需要扩展 Container
,您应该扩展 JPanel
,因为 JFrame
是一个刚性容器,不能放在另一个容器中。见 this question and this one.
我想我没有遗漏任何东西,希望这对您有所帮助
您的“缩放”图像实际上是与原始图像相同大小的图像,但除了在左上角绘制的缩放版本之外是空白的。在每个渲染单元格中,左上角都被剪掉了(至少对于我测试过的有点大的图像)。
需要使用缩略图大小而不是原始图像的大小创建缩放后的图像。意思是,改变这个:
BufferedImage bf = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
对此:
BufferedImage bf = new BufferedImage(thumbW, thumbH, BufferedImage.TYPE_INT_ARGB);
我正在写一个小照片应用程序(之前问过一些问题),但我有一个问题无法解决。这个想法是有两个部分:上面的部分用于概述(使用缩略图),下面的部分以全尺寸显示所选图像。我不能使用 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();
}
}
您的问题是因为您缩放图像的方式。
我不确定为什么,但我想这与 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);
}
这是我用来测试的文件夹:
你的代码和我的代码的输出:
重要提示
作为建议,如果您使用的只是上面那个小栏,则不要将 window 设置得那么大。如果您要在下面添加其他内容,那没关系,但现在还不是 "user friendly"(恕我直言)。而不是 JFrame#setSize()
you could try using 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
,您应该改为创建它的一个实例,除非您要覆盖它的其中一个方法(而您没有,所以不要这样做) 或者您有充分的理由这样做。如果您需要扩展Container
,您应该扩展JPanel
,因为JFrame
是一个刚性容器,不能放在另一个容器中。见 this question and this one.
我想我没有遗漏任何东西,希望这对您有所帮助
您的“缩放”图像实际上是与原始图像相同大小的图像,但除了在左上角绘制的缩放版本之外是空白的。在每个渲染单元格中,左上角都被剪掉了(至少对于我测试过的有点大的图像)。
需要使用缩略图大小而不是原始图像的大小创建缩放后的图像。意思是,改变这个:
BufferedImage bf = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
对此:
BufferedImage bf = new BufferedImage(thumbW, thumbH, BufferedImage.TYPE_INT_ARGB);