3

Ok im really struggling with unlocking my GUI which is locked due to separate SwingWorker thread. 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). I am aiming to obtain such result:

Grab frame -> process it -> display as ImageIcon of Jlabel > ... repeat Grab frame >...

I need results while webcam is streaming, therefore i used SwingWorker publish and process. 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). 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.

Generally i have 2 problems:

  • no JLabel icon update
  • Locked GUI

My SwingWorker code:

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. All my previous efforts also locked gui so tried the 'tutorial way', nonetheless it did not work, which is a pity. 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.

Community
  • 1
  • 1
Marian Pazioch
  • 83
  • 1
  • 10

4 Answers4

4

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.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • well yes, i was my further "concern" about the image order, since initially i wanted to process all gathered images, but thought that my program cant handle it that fast so i just grabbed last one (+ wanted to stick with tutorial example to dont mess anyting). According to publishing ImageIcon -> good point, i'll probably do so, however my bigger concern now is completely locked gui with no image update at all. – Marian Pazioch Jul 01 '11 at 12:28
  • INCREDIBLE, i meand serioulsy, i made some debug and noticed that i'm locked in `process`, therefore i tried to gather all pictures incoming, and it worked! Maybe there was an issue that always new images was comming to list. Nonetheless you inspired me to try it, so THANK YOU, i'm unbelievably grateful. – Marian Pazioch Jul 01 '11 at 13:22
  • btw. i have another question, my `List mystuff` get loaded with lots of images, shall i perfrom some `mystuff.clear();` at the end of `process` or its "cleaned" automatically/reinitialized each call of `process`? [couldnt find such information anywhere, therefor i ask] (i'd like to make my program optimal and stacking 10k images seems kinda memory waste) – Marian Pazioch Jul 01 '11 at 14:29
  • @Marian: I'm sorry, but I don't know. You may wish to ask another new question/thread topic on this, and hopefully one of the Swing gurus will know the answer. – Hovercraft Full Of Eels Jul 01 '11 at 14:30
3

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. Try, running a profiler or adding System.out.println in your code to find what is running while the GUI is locked.

Last, make sure you don't need to be repainting, revalidating the Label's container to make the image visible.

jzd
  • 23,473
  • 9
  • 54
  • 76
  • Well getting one frame + displaying it on button click i no problem, as well as making a thread for single frame grab&display. My aim is to avoid button clicks in order to get frame & process it further as i want to do it continously. Second: `process` and `doInBackground` are running continuously, but JLabel is not updated (however as i stated before - making there additional code for image save on local drive - works, so i have no clue how to force worker to update my gui) – Marian Pazioch Jul 01 '11 at 12:11
  • 1
    ok i made some debug, and finally resolved issue, ~~somehow i got locked in `process`, problem solved. Thanks to all for effort of help. – Marian Pazioch Jul 01 '11 at 13:24
  • @jzd: process is supposed to loop. I'm not sure why, but that's how it works. If Rob Camick or TrashGod were here, I'm sure they'd know why. 1+ for the debug suggestions. :) – Hovercraft Full Of Eels Jul 01 '11 at 13:30
1

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

Community
  • 1
  • 1
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • hmm, timers are something i wanted to avoid due to fact that they will make some delays which are highly undesirable when i want to obtain as fast as possible image processing, however i'll look on that one, maybe i'll learn something useful – Marian Pazioch Jul 01 '11 at 12:39
  • @Marian Pazioch then carrefully with number of threads called from `Executor`, because `SwingWorker` doesn't any care about `Executor` and vice-versa, and by this ignorance is there bugs in top 25 :-), and implemented `PropertyChangeListener` can hepl you with that or avoid expexted/non-expected/possible problems ... – mKorbel Jul 01 '11 at 12:46
0

Have you tried to set the label to observe the image icon?

icon.setImageObserver(label);
Garrett Hall
  • 29,524
  • 10
  • 61
  • 76