我一直在寻找一种以类似网格的方式在JPanel上显示图像的方法,并遇到this solution。代码工作得很好但是当我尝试使用jpg
图像而不是绘制矩形来修改它时,我无法使其工作。我的修改如下:
/*
* courtesy of https://stackoverflow.com/questions/7222988/java-drag-and-drop-images- in-a-list
*/
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.io.Serializable;
import javax.swing.*;
import javax.swing.border.Border;
public class ImagePreviewList {
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
JFrame frame = new JFrame("Image panel");
frame.setSize(800, 300);
frame.setLocationByPlatform(true);
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());
imageList.setCellRenderer(new ImageCellRenderer());
imageList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
imageList.setVisibleRowCount(-1);
imageList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
imageList.setFixedCellWidth(240);
imageList.setFixedCellHeight(120);
imageList.setDragEnabled(true);
imageList.setDropMode(DropMode.INSERT);
imageList.setTransferHandler(new ImageTransferHandler(imageList));
return imageList;
}
private static DefaultListModel createModel() {
DefaultListModel model = new DefaultListModel();
model.addElement(new RTS_image("3-Way_Stop_sign"));
model.addElement(new RTS_image("4-Way_Stop_sign"));
model.addElement(new RTS_image("No_Entry_sign"));
model.addElement(new RTS_image("One-Way_Roadway_sign-0"));
model.addElement(new RTS_image("One-Way_Roadway_sign-1"));
model.addElement(new RTS_image("One-Way_Roadway_sign-3"));
model.addElement(new RTS_image("Pedestrian-Priority_sign"));
model.addElement(new RTS_image("Stop#Go_sign"));
model.addElement(new RTS_image("Stop_and_Yield_sign"));
model.addElement(new RTS_image("Stop_sign-0"));
model.addElement(new RTS_image("Stop_sign-1"));
model.addElement(new RTS_image("Yield_at_Mini-Circle_sign"));
model.addElement(new RTS_image("Yield_sign"));
model.addElement(new RTS_image("Yield_to_Pedestrians_sign"));
model.addElement(new RTS_image("Yield_to_oncoming_traffic_sign"));
return model;
}
static class ImageTransferHandler extends TransferHandler {
private static final DataFlavor DATA_FLAVOUR = new DataFlavor(RTS_image.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 {
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.CENTER);
add(descriptionLabel, BorderLayout.SOUTH);
}
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);
descriptionLabel.setText("Description");
return this;
}
}
static class RTS_image implements Icon, Serializable {
private String Name_of_RoadSign;
RTS_image(String name_of_roadsign) {
this.Name_of_RoadSign = name_of_roadsign;
}
java.net.URL imgURL = com.umusebo.RTS.ImagePreviewList.class.getResource("images/01_Regulatory_Signs/01_Control_Signs/reg_cont_" + Name_of_RoadSign + ".jpg");
Image img = Toolkit.getDefaultToolkit().createImage(imgURL);
public void paintIcon(Component c, Graphics g, int x, int y) {
g.drawImage(img, x, y, c);
}
public int getIconWidth() {
return 114;
}
public int getIconHeight() {
return 125;
}
public String getName_of_RoadSign() {
return Name_of_RoadSign;
}
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) {
return false;
}
return Name_of_RoadSign.equals(((RTS_image)o).Name_of_RoadSign);
}
}
}
执行后,我得到以下错误(对于我试图显示的15张图片重复15次):
Uncaught error fetching image:
java.lang.NullPointerException
at sun.awt.image.URLImageSource.getConnection(URLImageSource.java:115)
at sun.awt.image.URLImageSource.getDecoder(URLImageSource.java:125)
at sun.awt.image.InputStreamImageSource.doFetch(InputStreamImageSource.java:263)
at sun.awt.image.ImageFetcher.fetchloop(ImageFetcher.java:205)
at sun.awt.image.ImageFetcher.run(ImageFetcher.java:169)
问题出在哪里?
答案 0 :(得分:3)
您已尝试使用null
例如,您要从变量imgURL
声明Name_of_RoadSign
null
,这将是java.net.URL imgURL = com.umusebo.RTS.ImagePreviewList.class.getResource(
"images/01_Regulatory_Signs/01_Control_Signs/reg_cont_"
+ Name_of_RoadSign + ".jpg");
。
RTS_image(String name_of_roadsign) {
this.Name_of_RoadSign = name_of_roadsign;
imgURL = com.umusebo.RTS.ImagePreviewList.class.getResource(
"images/01_Regulatory_Signs/01_Control_Signs/reg_cont_"
+ Name_of_RoadSign + ".jpg");
img = Toolkit.getDefaultToolkit().createImage(imgURL);
}
您必须记住,在执行任何类构造函数之前,都会初始化类字段。
尝试在构造函数中初始化这些类变量
ToolKit#createImage
null
倾向于默默地忽略错误,即使无法加载图像,也会返回无ImageIO
值。你更善于使用img = ImageIO.read(imgURL);
。除了支持更大范围的图像格式之外,它还会抛出更有意义的异常,从而更容易诊断问题。
例如......
IOException
不要忘记,这会抛出一个{{1}},所以你需要抓住它,或者(更好的是)将它传回给调用者。
我还鼓励您熟悉Code Conventions for the Java Programming Language。你不会通过忽视他们而成为任何朋友或影响他人。 ;)