【问题标题】:SwingWorker locks GUI on (unsuccessful) JLabel Icon updatingSwingWorker 将 GUI 锁定在(不成功的)JLabel 图标更新上
【发布时间】:2011-09-26 17:05:14
【问题描述】:

好吧,我真的很难解锁由于单独的 SwingWorker 线程而被锁定的 GUI。基本上我的程序是做什么的:初始化网络摄像头,然后抓取单帧并将其显示为 JLabel 图标(在单击按钮时进行单次抓取+显示很容易,但是我在连续执行此类操作以进行一些图像处理时遇到了巨大的困难) .我的目标是获得这样的结果:

抓取框架 -> 处理它 -> 显示为 Jlabel 的 ImageIcon > ...重复抓取框架 >...

我需要网络摄像头流式传输时的结果,因此我使用了 SwingWorker publishprocess。在我的代码中,“处理部分”不包括在内,因为它没有必要,因为我什至无法获得适当的连续帧抓取。通常,除非取消,否则我的后台线程永远不会完成(这就是假设,因为我想以每秒最大帧数尽可能快地处理图像-除非我应该以其他方式进行?-我想用于单帧抓取和处理的单独线程会很糟糕想法是因为我的目标是获得 10+ FPS)。我知道我的 SwingWorker 线程可以工作,因为我进行了将连续图像保存到 C:\ 的测试,它确实有效,但我的 GUI 无论如何都被锁定了,但至少我知道该线程正在运行并抓取帧。

一般我有两个问题:

  • 没有 JLabel 图标更新
  • 锁定的 GUI

我的 SwingWorker 代码:

private class FrameStream extends SwingWorker<Void, BufferedImage> { 
    @Override
    protected Void doInBackground() throws InterruptedException{
        BufferedImage processedImage = null;
        
        while (!isCancelled()) {
            processedImage = getPIC_COLOR(player);
            publish(processedImage);
            
            Thread.sleep(5000); // i made such delay to check whether program is not "choking" with data, but its not the case, without this delay everthing is the same
        }            
        return null;
    }

    @Override
    protected void process(List<BufferedImage> mystuff) {
        Iterator it = mystuff.iterator(); 

        while (it.hasNext()) {
            img_field.setIcon(new ImageIcon(mystuff.get(mystuff.size()-1)));
        }
    }

    @Override
    protected void done() {            
        infoBAR.setText("FINISHED");
    }
}

我非常绝望,我完全根据教程示例重写了我的代码:Flipper 你可以看到它非常相似。我之前的所有努力也锁定了gui,所以尝试了'教程方式',但它没有奏效,很遗憾。我陷入了死胡同,因为我不知道如何解决这个问题。我迫切需要帮助,因为您可以看到它与教程一模一样,可能是其他原因导致问题:MY FULL CODE

请帮忙,我自己解决不了。

【问题讨论】:

  • 我建议使用jstack(和jps)找出您的代码被锁定的位置。

标签: java multithreading swing user-interface swingworker


【解决方案1】:

你试过设置标签来观察图片图标吗?

icon.setImageObserver(label);

【讨论】:

    【解决方案2】:

    hmmmm,如果我读到你的last post 关于这个问题,可能有很多可能的错误(我看到你的代码),这与SwingWorker 无关,另一个example 只是替换更改颜色为@ 987654324@ 与您的Icon or ImageIcon

    【讨论】:

    • hmm,计时器是我想避免的,因为当我想获得尽可能快的图像处理时,它们会产生一些非常不希望的延迟,但是我会看看那个,也许我会学到一些有用的东西
    • @Marian Pazioch 然后小心翼翼地使用从Executor 调用的线程数,因为SwingWorker 不关心Executor,反之亦然,由于这种无知,顶部是否存在错误25 :-),并实施 PropertyChangeListener 可以帮助您或避免预期/非预期/可能的问题...
    【解决方案3】:

    在我看来有点不同的是你的处理方法。您可能希望像这样遍历所有图像,而不是指定最后一张图像:

      @Override
      protected void process(List<BufferedImage> mystuff) {
         for (BufferedImage bImage : mystuff) {
            img_field.setIcon(new ImageIcon(bImage));
         }
      }
    

    我不确定这是否会产生重大影响,但我相信应该这样编写流程。另一个想法——如果 BufferedImage 很大,您可能希望在后台线程中创建 ImageIcon 并发布 ImageIcon 而不是 BufferedImage。

    【讨论】:

    • 好吧,是的,我对图像顺序更加“担心”,因为最初我想处理所有收集的图像,但认为我的程序无法快速处理它,所以我只抓住了最后一张( + 想坚持使用教程示例,以免弄乱任何东西)。根据发布 ImageIcon -> 好点,我可能会这样做,但是我现在更担心的是完全锁定 gui,根本没有图像更新。
    • 难以置信,我的意思是serioulsy,我做了一些调试,发现我被锁定在process,因此我试图收集所有传入的图片,它成功了!也许有一个问题,总是有新的图像出现在列表中。尽管如此,你激励我尝试它,所以谢谢你,我非常感激。
    • @Marian:不客气。很高兴它有帮助!这是我在您的代码中看到的唯一错误,所以我认为尝试更改它不会有什么坏处。
    • 顺便说一句。我还有一个问题,我的List&lt;BufferedImage&gt; mystuff 加载了很多图像,我应该在process 的末尾执行一些mystuff.clear(); 还是自动/重新初始化process 的每个调用? [在任何地方都找不到这样的信息,因此我问](我想让我的程序优化,堆叠 10k 图像似乎有点浪费内存)
    • @Marian:对不起,我不知道。您可能希望就此提出另一个新问题/线程主题,并希望 Swing 大师中的一位知道答案。
    【解决方案4】:

    没有什么是突出的问题。我建议进一步调试的步骤。

    不使用循环和处理方法,只需拉一帧并设置一次图标。在尝试使其循环之前,您需要使其正常工作。您的应用程序应该能够设置图标,使其不会突出显示问题。

    其次,由于您的 GUI 已锁定,EDT 上仍有一些事情发生。尝试运行分析器或在代码中添加 System.out.println 以查找 GUI 锁定时正在运行的内容。

    最后,确保您不需要重新绘制、重新验证标签的容器以使图像可见。

    【讨论】:

    • 获得一帧+在按钮单击时显示它没问题,以及为单帧抓取和显示创建线程。我的目标是避免单击按钮以获取框架并进一步处理它,因为我想连续进行。第二:processdoInBackground 连续运行,但 JLabel 没有更新(但是,正如我之前所说 - 在本地驱动器上制作额外的图像保存代码 - 有效,所以我不知道如何强制工人更新我的gui)
    • 好的,我做了一些调试,终于解决了问题,~~不知怎么我被锁定在process,问题解决了。感谢大家的帮助。
    • @jzd:进程应该循环。我不知道为什么,但这就是它的工作原理。如果 Rob Camick 或 TrashGod 在这里,我相信他们会知道原因。 1+ 用于调试建议。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多