java - 调用 mouseClicked() 后 JComponent 消失

标签 java swing awt swingworker jcomponent

我正在使用 Swing 编写 Java GUI 程序。界面如下所示:

program

当用户单击右侧的其中一张图片时,我希望在左上角的橙色区域中显示它的小预览。我通过 SwingWorker thread 从计算机上的目录中提取所有图像文件。 。在 SwingWorker 的 done() method ,我向每个对象添加一个 mouseClicked 监听器(来 self 创建的类的 TaggableImage 对象。它具有 BufferedImage 并扩展 JComponent,覆盖 paintComponent() 方法)。在 mouseClicked 监听器中,我调用橙色面板的 add() 方法并向其传递 TaggableImage。

我的问题:

当我单击其中一张图像时,它不会添加到橙色面板中,并且会从右侧面板中消失。如果我单击所有图像,我将留下一个空白的右侧面板。为什么会出现这种情况?

这是我的整个 SwingWorker 线程:

SwingWorker<ArrayList<TaggableImage>, Void> loadImagesAsyncWorker = new SwingWorker<ArrayList<TaggableImage>, Void>() {

    ArrayList<TaggableImage> img_list = new ArrayList<TaggableImage>();

    @Override
    protected ArrayList<TaggableImage> 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);
    }
}

最佳答案

考虑对右侧面板使用 JList 以利用灵活的布局选项和选择处理,如图 here 所示及以下。

enter image description here

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();
        });
    }
}

关于java - 调用 mouseClicked() 后 JComponent 消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25167235/

相关文章:

java - java中输入语句的比较

java - java和php之间简单的客户端服务器通信

swing - 如何在 jFrame 上创建带有关闭按钮的自定义标题栏?

java - 为什么在将组件添加到容器时 AWT/Swing 不自动重绘?

java - 从监听器中修改 JFrame

java - 如何将二进制文件存储到数组中并将其放入不同的标签(编译程序)?

java - Derby - java.sql.SQLException : Column 'table.column_name' not found

java - WireMock 可以回放来自多个域的请求吗?

java - 为什么我必须导入 java.awt.* 和 java.awt.event.* (例如)

java - 跟踪每次选中和取消选中复选框的时间