简体   繁体   English

SwingWorker 将 GUI 锁定在(不成功的)JLabel 图标更新上

[英]SwingWorker locks GUI on (unsuccessful) JLabel Icon updating

Ok im really struggling with unlocking my GUI which is locked due to separate SwingWorker thread.好的,我真的在努力解锁由于单独的 SwingWorker 线程而被锁定的 GUI。 Basically what my program does: Initializes webcam, and then grabs single frame and displays it as JLabel icon (doing single grab+display on Button click is ease, however i have immense difficulties in doing such operation consecutively in order to do some image processing).基本上我的程序是做什么的:初始化网络摄像头,然后抓取单帧并将其显示为 JLabel 图标(在单击按钮时进行单次抓取+显示很容易,但是我在连续执行此类操作以进行一些图像处理时遇到了巨大的困难) . I am aiming to obtain such result:我的目标是获得这样的结果:

Grab frame -> process it -> display as ImageIcon of Jlabel >... repeat Grab frame >...抓取框架 -> 处理它 -> 显示为 Jlabel 的 ImageIcon >... 重复抓取框架 >...

I need results while webcam is streaming, therefore i used SwingWorker publish and process .我在网络摄像头流式传输时需要结果,因此我使用了 SwingWorker publishprocess In my code "processing part" is not included as it is not necessary since i cant even obtain proper continuous frame grabbing.在我的代码中,“处理部分”不包括在内,因为它没有必要,因为我什至无法获得正确的连续帧抓取。 Generally my background thread will never finish unless cancelled (well thats the assumption as i want to process images as fast as possible with maximum frames per second - unless i should do it other way? - i guess separate thread for single frame grab&process would be bad idea due to fact that im aiming to get 10+ FPS).通常,除非取消,否则我的后台线程永远不会完成(这就是假设,因为我想以每秒最大帧数尽可能快地处理图像-除非我应该以其他方式进行?-我想用于单帧抓取和处理的单独线程会很糟糕想法是因为我的目标是获得 10+ FPS)。 I know my SwingWorker thread works, since i made tests of saving consecutive images to C:\, and it did work, but my GUI is locked anyway, but at least i know that thread is running and grabbing frames.我知道我的 SwingWorker 线程有效,因为我测试了将连续图像保存到 C:\,它确实有效,但我的 GUI 无论如何都被锁定,但至少我知道该线程正在运行并抓取帧。

Generally i have 2 problems:通常我有2个问题:

  • no JLabel icon update没有 JLabel 图标更新
  • Locked GUI锁定的 GUI

My SwingWorker code:我的 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");
    }
}

I am so desperate that i rewritten my code completely basing on tutorials example: Flipper as you can see it is ridiculously similar.我非常绝望,以至于我完全根据教程示例重写了我的代码: Flipper ,你可以看到它非常相似。 All my previous efforts also locked gui so tried the 'tutorial way', nonetheless it did not work, which is a pity.我之前的所有努力也锁定了gui,所以尝试了'教程方式',但它没有奏效,很遗憾。 Im in a dead end because i have no clue how to fix that.我陷入了死胡同,因为我不知道如何解决这个问题。 Im desperate for help since as you can see it seems exactly the same as the tutorial one, maybe something other causes issues: MY FULL CODE我迫切需要帮助,因为正如您所看到的,它似乎与教程一模一样,也许是其他原因导致的问题:我的完整代码

Please help, i'm unable to solve it by myself.请帮忙,我自己无法解决。

One thing that looks a little different to me is your process method.对我来说看起来有点不同的一件事是你的处理方法。 Rather than specifying the last image, you might wish to iterate through all images like so:您可能希望像这样遍历所有图像,而不是指定最后一张图像:

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

I'm not sure if this will make a significant difference, but I believe that this is how process should be written.我不确定这是否会产生重大影响,但我相信这就是应该编写流程的方式。 Another thought -- if the BufferedImages are large you may wish to create the ImageIcon in the background thread and publish the ImageIcon rather than the BufferedImage.另一个想法——如果 BufferedImage 很大,您可能希望在后台线程中创建 ImageIcon 并发布 ImageIcon 而不是 BufferedImage。

Nothing stands out as an issue.没有什么是突出的问题。 Steps I would suggest to further debug.我建议进一步调试的步骤。

Instead of using a loop and the process method, just pull one frame and set the Icon once.而不是使用循环和处理方法,只需拉一帧并设置一次图标。 You need to get that working before you try to make it loop.在尝试使其循环之前,您需要使其正常工作。 Your application should be able to set the icon that fact that it doesn't highlights a problem.您的应用程序应该能够将图标设置为不会突出显示问题的事实。

Second, because your GUI is locking up, there is something still happening on the EDT.其次,由于您的 GUI 已锁定,因此 EDT 上仍在发生某些事情。 Try, running a profiler or adding System.out.println in your code to find what is running while the GUI is locked.尝试运行分析器或在代码中添加System.out.println以查找 GUI 锁定时正在运行的内容。

Last, make sure you don't need to be repainting, revalidating the Label's container to make the image visible.最后,确保您不需要重新绘制、重新验证标签的容器以使图像可见。

hmmmm, if I read your last post about this issue, there are maybe lots of possible mistakes (and I see your code), that's nothing to do with SwingWorker , another example just replace change Color for JButton#setBackground() with your Icon or ImageIcon嗯,如果我读了你关于这个问题的一篇文章,可能有很多可能的错误(我看到你的代码 ,这与SwingWorker无关,另一个例子只是用你的Icon 或图像图标

Have you tried to set the label to observe the image icon?您是否尝试过设置 label 来观察图像图标?

icon.setImageObserver(label);

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

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