Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java等待绘制组件_Java_Swing_Jpanel_Jcomponent - Fatal编程技术网

Java等待绘制组件

Java等待绘制组件,java,swing,jpanel,jcomponent,Java,Swing,Jpanel,Jcomponent,我正在尝试用Java创建一个程序,它将一个接一个地显示一组图像,并为每个图像调整帧的大小。 我正在扩展JPanel以显示如下图像: public class ImagePanel extends JPanel{ String filename; Image image; boolean loaded = false; ImagePanel(){} ImagePanel(String filename){ loadImage(filename); } public void pai

我正在尝试用Java创建一个程序,它将一个接一个地显示一组图像,并为每个图像调整帧的大小。 我正在扩展JPanel以显示如下图像:

public class ImagePanel extends JPanel{

String filename;
Image image;
boolean loaded = false;

ImagePanel(){}

ImagePanel(String filename){
    loadImage(filename);
}

public void paintComponent(Graphics g){
    super.paintComponent(g);
    if(image != null && loaded){
        g.drawImage(image, 0, 0, this);
    }else{
        g.drawString("Image read error", 10, getHeight() - 10);
    }
}

public void loadImage(String filename){
    loaded = false;         
    ImageIcon icon = new ImageIcon(filename);
    image = icon.getImage();
    int w = image.getWidth(this);
    int h = image.getHeight(this);
    if(w != -1 && w != 0 && h != -1 && h != 0){
        setPreferredSize(new Dimension(w, h));
        loaded = true;
    }else{
        setPreferredSize(new Dimension(300, 300));
    }
}
}

然后在事件线程中,我正在做主要工作:

        SwingUtilities.invokeLater(new Runnable(){

        @Override
        public void run(){
            createGUI();
        }
    });
在createGUI()中,我将浏览一组图像:

        ImagePanel imgPan = new ImagePanel();
    add(imgPan);

    for(File file : files){
        if(file.isFile()){
            System.out.println(file.getAbsolutePath());

            imgPan.loadImage(file.getAbsolutePath());
            pack();

            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } 
        }
    }
问题是,我的程序正确地调整了大小,所以图像加载正确,但它不显示任何内容。 如果我只显示一个图像,它也适用于最后一个图像。我认为问题在于在图像绘制完成之前调用了Thread.sleep()

我怎样才能等待ImagePanel完成绘制,然后再开始等待? 还是有别的办法解决这个问题

谢谢!
Leonty

使用计时器并启动下一个映像作为事件,而不是使线程睡眠。

所有代码都在事件调度线程上执行。这有效地导致所有用户交互休眠,因为事件调度线程负责所有用户交互——输入(事件)和输出(绘制)

你需要让你的等待发生在EDT之外。您需要知道如何在EDT上和下执行事件。为此,您可以创建一个新的
Runnable
,然后调用
new Thread(Runnable)
在EDT之外执行它,或者调用
SwingUtilities.invokeLater(Runnable)
在EDT上执行它。与Swing组件的所有交互都需要在EDT上进行,因为Swing对象不是线程安全的。所有睡眠、等待、文件访问、网络访问、数据库访问或任何其他可能阻塞不确定时间段的操作都必须在EDT之外进行


堆栈溢出有许多问题与事件调度线程有关。我建议您查看这些内容,以找到更多信息和代码示例,以便以不同的方式执行您希望执行的操作。

听起来您希望图像在加载时逐个显示(如在网页中),对吗?如果是这样的话,您当前的代码就不会得到这种效果,因为在加载所有图像之前,您的UI不会更新,这是因为您正在EDT(事件调度线程)上加载图像,而EDT是进行绘制的同一线程。绘画发生在“有时间的时候”,在这种情况下,这意味着在加载所有图像之后

为了解决您的问题,我建议您创建一个子类,如下所示:

公共类MyImageLoader扩展SwingWorker
{
//在后台线程中执行,EDT可以同时加载和绘制图像
@凌驾
受保护的Void doInBackground()引发异常
{
用于(文件:文件)
{
if(file.isFile())//可能需要更多的检查,看看它是否是图像
{
发布(文件.getAbsolutePath());
睡眠(500);
}
}
}
//于美国东部时间执行
@凌驾
受保护的无效进程(列出文件路径)
{
for(字符串路径:文件路径)
{
//将ImageIcon加载到UI
}
}
}

谢谢!这让我走上了正确的道路!我现在在主线程中执行代码,所有操作现在都是同步的,所以等待只有在绘制完成后才会发生。我尝试了,但它成功了,但我需要使用pack()来调整每个图像的窗口大小,我遇到了同样的问题-我需要知道绘制完成后调用“pack()”。
public class MyImageLoader extends SwingWorker<Void, String>
{
    // Is executed in background thread, EDT can meanwhile load and paint images
    @Override
    protected Void doInBackground() throws Exception
    {
        for(File file : files)
        {
             if(file.isFile()) // Maybe some more check to see if it's an image
             {
                 publish(file.getAbsolutePath());
                 Thread.sleep(500);
             }
        }
    }

    // Executed on EDT
    @Override
    protected void process(List<String> filePaths)
    {
        for(String path : filePaths)
        {
            // Load ImageIcon to UI
        }
    }
}