繁体   English   中英

如何在 ImageLoader 中同步 ImageIcon

[英]How to synchronize ImageIcon in ImageLoader

我最近开始在 Java 中使用多线程,但遇到了一个问题,我认为是由于缺少同步。

这是我写的 ImageLoader:

package util;

import javax.swing.ImageIcon;
                                          
public class ImageLoader extends Thread {

    private String file;
    private ImageIcon icon;
    
    public ImageLoader(String file) {
        this.file = file;
    }
    
    @Override
    public void run() {
        
        ImageIcon icon = new ImageIcon(this.file);
        this.icon = icon;
        super.run();
    }
    
    public synchronized ImageIcon returnIcon() {
        return this.icon;
    }

}

我在我的 GUI 类中使用这个 ImageLoader:

package gui;

import java.awt.Dimension;
import java.awt.GridLayout;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import util.ImageLoader;

public class HauptGui extends JComponent {

    public HauptGui() {
        initUI();
    }

    private void initUI() {
        
        int bilderAnzahl = 3;
        
        this.setLayout(new GridLayout(1, 1));
        
        JPanel  bilderPanel = new JPanel(new GridLayout(bilderAnzahl, 1));
        for (int i = 0; i < bilderAnzahl; i++) {
            JLabel jbl = new JLabel();
            ImageLoader loader = new ImageLoader("./Picture.jpg");
            loader.start();
            jbl.setIcon(loader.returnIcon());           
            jbl.setBorder(BorderFactory.createEtchedBorder());
            jbl.setPreferredSize(new Dimension(200, 50));
            bilderPanel.add(jbl);
        }
        
        JScrollPane scrPn = new JScrollPane(bilderPanel);
        
        this.add(scrPn);
        
    }
    
}

问题是在线程调用 run-Method 之前调用了 ImageLoader 的 returnIcon-Method,因此 ImageIcon 仍然为 null。

我如何同步这个?

不,您的问题与同步无关,而与在创建图像对象之前简单地请求图像对象有关。 解决方案是在完成加载后在回调中获取图像对象。 在这种情况下,SwingWorker 可以很好地工作,在这种情况下,您可以通过调用.get()从工作人员的 done 方法中的 SwingWorker 获取图像对象,或者您可以使用 PropertyChangeListener 进行回调。 有关如何使用 SwingWorkers 的详细信息,请参见课程:Swing中的并发

例如(代码未测试)

public class ImageLoader2 extends SwingWorker<BufferedImage, Void> {
    private String path = "";  /// String to resource path
    
    public BufferedImage doInBackground() throws Exception {
        return ImageIO.read(ImageLoader2.class.getResource(path));
    }
    
}

然后像这样运行它:

ImageLoader2 loader = new ImageLoader2();

loader.addPropertyChangeListener(pce -> {
    if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
        try {
            BufferedImage img = loader.get();
            ImageIcon icon = new ImageIcon(img);
            
            // use icon here...
            
        } catch catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
            // handle exception here
        }
    }
});
loader.execute();

旁注

  1. 你几乎应该扩展 Thread。
  2. 不要像您一样将图像作为文件获取,而是将其作为资源获取并使用ImageIO.read(...)来执行此操作
  3. 资源路径是相对于类路径的,而不是相对于用户目录的,因此它可能与您用来将图像作为文件获取的路径不同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM