我正在用Swing編寫Java GUI程序。該界面如下所示:
當用戶單擊右側的圖片之一時,我希望它的一個小的預覽顯示在左上角的橙色區域中。我通過SwingWorker線程從計算機上的目錄中提取所有圖像文件。在SwingWorker的done()方法中,我向每個對象添加了mouseClicked偵聽器(我創建的類中的TaggableImage對象。它具有BufferedImage并擴展了JComponent,覆蓋了paintComponent()方法)。在mouseClicked偵聽器中,我調用橙色面板的add()方法并將其傳遞給TaggableImage。
我的問題:
當我單擊其中一張圖像時,它不會被添加到橙色面板中,并且會從右側面板中消失。如果單擊所有圖像,則會在右側面板空白。為什么會這樣?
這是我的整個SwingWorker線程:
SwingWorker, Void> loadImagesAsyncWorker = new SwingWorker, Void>() {
ArrayList img_list = new ArrayList();
@Override
protected ArrayList doInBackground() throws Exception {
File currentDirectory = new File(".");
getFileInDirectory(currentDirectory);
return null;
}
// recursively get all files in this directory and child directories
private void getFileInDirectory(File cd) {
File[] file_list = cd.listFiles();
for (File f : file_list) {
if (f.isDirectory()) {
getFileInDirectory(f);
} else if (f.isFile()) {
BufferedImage bf = null;
String extension ="";
int i = f.getName().lastIndexOf('.');
int p = Math.max(f.getName().lastIndexOf('/'), f.getName()
.lastIndexOf('\'));
if (i > p) {
extension = f.getName().substring(i + 1);
}
System.out.println(f.getName());
if (extension.equals("jpg")) {
try {
bf = ImageIO.read(f);
TaggableImage ti = new TaggableImage(bf);
img_list.add(ti);
} catch (IOException e) {
}
}
}
}
}
public void done() {
for (TaggableImage ti : img_list) {
final TaggableImage final_ti = ti;
ti.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
final_ti.setMaximumSize(new Dimension(30, 30));
BorderLayout layout = (BorderLayout) getContentPane()
.getLayout();
if (layout.getLayoutComponent(BorderLayout.CENTER) != null) {
img_prev_panel.remove(layout
.getLayoutComponent(BorderLayout.CENTER));
}
//img_prev_panel = the orange panel
img_prev_panel.add(final_ti, BorderLayout.CENTER);
});
}
}
};
這是我的TaggableImage類:
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import javax.swing.JComponent;
public class TaggableImage extends JComponent {
private static final long serialVersionUID = 1L;
private BufferedImage bufferedImage;
private int height;
private int width;
public TaggableImage(BufferedImage bufferedImage) {
this.bufferedImage = bufferedImage;
}
public TaggableImage(BufferedImage bufferedImage, int width, int height) {
this.bufferedImage = bufferedImage;
this.width = width;
this.height = height;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(bufferedImage, 0, 0, null);
}
}
考慮發布MCVE。 請注意,一個組件只能有一個父級。 重新設定父級時,將從舊父級中刪除該組件。 因此,當您將組件添加到img_prev_panel時,將從另一個容器中將其刪除。
有沒有一種方法可以將一個組件復制到另一個組件,同時為副本提供新的父對象?
您可以共享圖像,在一個組件中顯示縮略圖版本,在另一個組件中顯示完整尺寸。
我為此找到了Thumbnailator。
考慮在右側面板上使用JList來利用靈活的布局選項和選擇處理,如下所示。
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
/**
* @see https://stackoverflow.com/a/25170471/230513
*/
public class ListDisplayPanel {
private static final Icon icon = UIManager.getIcon("html.pendingImage");
private ListPanel listPanel = new ListPanel();
private DisplayPanel displayPanel = new DisplayPanel();
private class DisplayPanel extends JPanel {
private static final int SIZE = 256;
private JLabel label = new JLabel();
public DisplayPanel() {
this.add(label);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage img = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D temp = (Graphics2D) img.getGraphics();
icon.paintIcon(this, temp, 0, 0);
temp.dispose();
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.drawImage(img, 0, 0, getWidth(), getHeight(), this);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(SIZE, SIZE);
}
}
private class ListPanel extends JPanel {
private static final int N = 5;
private DefaultListModel dlm = new DefaultListModel();
private JList list = new JList(dlm);
public ListPanel() {
super(new GridLayout());
for (int i = 0; i < N * N; i++) {
String name ="Cell-" + String.format("%02d", i);
dlm.addElement(name);
}
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(N);
list.setCellRenderer(new ListRenderer());
list.addListSelectionListener(new SelectionHandler());
this.add(list);
}
private class ListRenderer extends DefaultListCellRenderer {
@Override
public Component getListCellRendererComponent(JList list,
Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(
list, value, index, isSelected, cellHasFocus);
label.setBorder(BorderFactory.createEmptyBorder(N, N, N, N));
label.setIcon(icon);
label.setHorizontalTextPosition(JLabel.CENTER);
label.setVerticalTextPosition(JLabel.BOTTOM);
return label;
}
}
private class SelectionHandler implements ListSelectionListener {
@Override
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
displayPanel.label.setText((String) dlm.getElementAt(e.getLastIndex()));
}
}
}
}
private void display() {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JSplitPane jsp = new JSplitPane();
jsp.setRightComponent(new JScrollPane(listPanel));
jsp.setLeftComponent(displayPanel);
f.add(jsp);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
new ListDisplayPanel().display();
});
}
}
或者,讓displayPanel包含SelectionHandler。