3

我正在尝试改进我的 SwingWorker 类 ImageWorker。ImageWorker 旨在用于大型图像数组。定期调用 ImageWorker 以加载新图像,同时将看到的图像的数组索引设置为 null。这就是为什么它只加载到 i < currentPosition+40 以防止它尝试一次性加载整个阵列,这对于较慢的机器来说太多了。目前它需要加载所有 40 张图像,然后才能在 EDT 上运行 done() 方法。在我没有时间提前启动 ImageWorker 的地方,这会导致几毫秒的延迟。

我想实现发布/处理,但我似乎找不到将这些方法与数组一起使用的示例。是否有使用具有数组返回类型的发布/处理的已知良好做法?或者我应该尝试将单个图像发布为 imageArray[i],然后使用过程将这些图像合并到适当的数组中?我似乎找不到任何将数组用于这些方法的代码,只有字符串和整数。

感谢垃圾神帮助我首先开始使用 ImageWorker。我最初的问题已经发展到足以证明它可能需要这个新线程。原始线程包含使用 ImageWorker 的代码的 SSCCE,可以在此处找到:完整代码

private class ImageWorker extends SwingWorker<Image[], Image>
{
    private int currentPosition;
    private int arraySize;
    private String trickName;
    private Image[] imageArray;

    public ImageWorker(int arraySize, int currentPosition, String trick)
    {
        super();
        this.currentPosition = currentPosition;
        this.arraySize = arraySize;
        this.trickName = trick;
    }

    @Override
    public Image[] doInBackground()
    {
        imageArray = new Image[arraySize];
        for(int i = currentPosition; i < currentPosition+40 && i < arraySize; i++)
        {
            try 
            {
                imageArray[i] = ImageIO.read(new File("images/" + trickName + (i+1) + ".jpg"));
            } 
            catch (IOException e) 
            {
                System.out.println(trickName);
                System.out.println(e.getMessage());
                System.exit(0);
            }
        }
        return imageArray;
    }

    @Override
    public void done()
    {
        try
        {
            if(trickName.equals("handCuffs"))
            {
                handCuffs = get();
            }
            else if(trickName.equals("cups"))
            {
                cups = get();
            }
        }
        catch(InterruptedException ignore){}
        catch(java.util.concurrent.ExecutionException e)
        {
            String why = null;
            Throwable cause = e.getCause();
            if(cause != null)
            {
                why = cause.getMessage();
            }
            else
            {
                why = e.getMessage();
            }
            System.err.println("Error retrieving file: " + why);
        }
    }
}

看来我应该在 for 循环中的每个图像上使用发布,然后使用过程将它们作为元素放入数组中。过程部分似乎更困难。我编辑了上面的代码以包含一个处理方法,但它还不能正常工作。

private class ImageWorker extends SwingWorker<Image[], Image>
{
    private int currentPosition;
    private int arraySize;
    private String trickName;
    private Image[] imageArray;

    public ImageWorker(int arraySize, int currentPosition, String trick)
    {
        super();
        this.currentPosition = currentPosition;
        this.arraySize = arraySize;
        this.trickName = trick;
        i = currentPosition;
    }

    @Override
    public Image[] doInBackground()
    {
        imageArray = new Image[arraySize];
        for(int i = currentPosition; i < currentPosition+40 && i < arraySize; i++)
        {
            try 
            {
                imageArray[i] = ImageIO.read(new File("images/" + trickName + (i+1) + ".jpg"));
                publish(imageArray[i], i);
            } 
            catch (IOException e) 
            {
                System.out.println(trickName);
                System.out.println(e.getMessage());
                System.exit(0);
            }
        }
        return imageArray;
    }

    @Override
    public void process(List<Image> chunks, int i)
    {
        for(Image element: chunks)
        {
            if(trickName.equals("handCuffs"))
            {
                handCuffs[i] = element;
            }
            else if(trickName.equals("cups"))
            {
                cups[i] = element;
            }
        }
    }

    @Override
    public void done()
    {
        try
        {
            if(trickName.equals("handCuffs"))
            {
                handCuffs = get();
            }
            else if(trickName.equals("cups"))
            {
                cups = get();
            }
        }
        catch(InterruptedException ignore){}
        catch(java.util.concurrent.ExecutionException e)
        {
            String why = null;
            Throwable cause = e.getCause();
            if(cause != null)
            {
                why = cause.getMessage();
            }
            else
            {
                why = e.getMessage();
            }
            System.err.println("Error retrieving file: " + why);
        }
    }
}

处理方法的问题是我不知道如何为发布的元素将被写入的数组设置正确的索引。我想发布以传递索引和图像,但这违反了类设置的返回类型。发布只能有一种类型的论据吗?

4

1 回答 1

3

感谢垃圾神和 MadProgrammer 提供的所有帮助。如果其他人想要实现类似的 SwingWorker,这是我的最终代码,包括用于封装 arrayImage[i] 的包装类和相应的索引 int i。

private class ArrayWrapper
{
    private int i;
    private Image image;

    public ArrayWrapper(Image image, int i)
    {
        this.i = i;
        this.image = image;
    }

    public int getIndex()
    {
        return i;
    }

    public Image getImage()
    {
        return image;
    }
}

private class ImageWorker extends SwingWorker<Image[], ArrayWrapper>
{
    private int currentPosition;
    private int arraySize;
    private String trickName;
    private Image[] imageArray;

    public ImageWorker(int arraySize, int currentPosition, String trick)
    {
        super();
        this.currentPosition = currentPosition;
        this.arraySize = arraySize;
        this.trickName = trick;
    }

    @Override
    public Image[] doInBackground()
    {
        imageArray = new Image[arraySize];
        for(int i = currentPosition; i < currentPosition+40 && i < arraySize; i++)
        {
            try 
            {
                imageArray[i] = ImageIO.read(new File("images/" + trickName + (i+1) + ".jpg"));
                ArrayWrapper wrapArray = new ArrayWrapper(imageArray[i], i);
                publish(wrapArray);
            } 
            catch (IOException e) 
            {
                System.out.println(trickName);
                System.out.println(e.getMessage());
                System.exit(0);
            }
        }
        return imageArray;
    }

    @Override
    public void process(List<ArrayWrapper> chunks)
    {
        for(ArrayWrapper element: chunks)
        {
            if(trickName.equals("handCuffs"))
            {
                handCuffs[element.getIndex()] = element.getImage();
            }
            else if(trickName.equals("cups"))
            {
                cups[element.getIndex()] = element.getImage();
            }
        }
    }

    @Override
    public void done()
    {
        try
        {
            if(trickName.equals("handCuffs"))
            {
                handCuffs = get();
            }
            else if(trickName.equals("cups"))
            {
                cups = get();
            }
        }
        catch(InterruptedException ignore){}
        catch(java.util.concurrent.ExecutionException e)
        {
            String why = null;
            Throwable cause = e.getCause();
            if(cause != null)
            {
                why = cause.getMessage();
            }
            else
            {
                why = e.getMessage();
            }
            System.err.println("Error retrieving file: " + why);
        }
    }
}
于 2013-01-11T05:39:16.237 回答