How to add images multiple times (issue with napari.gui_qt())

I cannot seem to properly be able to use with napari.gui_qt() in my application.

I initialize one instance of napari.gui_qt(), and later on use it to add an image to napari.

I get these errors:
`WARNING: WARNING: QApplication was not created in the main() thread.

  • Detected change in ‘C:\Users\brian\OneDrive\Desktop\aics\microscopeautomation-napari_viewer\napari_viewer\instance.py’, reloading
    WARNING: Cannot make QOpenGLContext current in a different thread`

Could anyone point me in the right direction to be able to utilize this correctly?

I initialize one instance of napari.gui_qt()

by this do you mean you are doing something like instance = napari.gui_qt()? If so, that’s not what napari.gui_qt() is for. It’s a context manager that “sets up the environment” for napari (specifically, it starts a Qt application):

import napari

with napari.gui_qt():
    viewer = napari.Viewer()
    viewer.add_image(...)

If that was the problem, have a look through our tutorials and examples for more usage examples… but if I misunderstood the problem, please let me know!

I’m not having any issues with using the context manager to do viewer.add_image().

After I use the context manager once, how am I supposed to use it again? I’m adding a bunch of images early on in my program, then later on I want to add more images as they become available. That is what I’m having issues with.

Thank you for your reply!

you should be able reuse the context multiple times if want … though it may “block” in ways you aren’t expecting.

However, while the context manager is great for one-off scripts, if you are creating something more like a program, you might want to create the Qt app once yourself.

In either case, it’s a lot easier to help if I could see what you’re trying to do … so if you can point me to your program, or paste code examples here of what you’re attempting that is specifically not working, I might be able to provide some advice.

1 Like

Okay, posting some snippets of my code.

                with self.gui_qt():
                    self.viewer = napari.Viewer()
                    for key in response_meta.keys():
                        resp = requests.get(DATA_URL + '/data/binary/' + key)
                        image = np.frombuffer(resp.content, dtype=response_meta[key]["format"]).reshape(response_meta[key]['image_dimensions'])
                        return_image = np.array(image, dtype=np.uint8)
                        self.viewer.add_image(return_image, name=key)

I initially do this to load all the images onto napari. While napari is open, I do this:

                with self.gui_qt():
                    self.viewer.add_image(return_image, name=resp["data_id"])

which does not work.

And what is self here? I still think there might be a misunderstanding about how to use gui_qt… I can’t think of a scenario in which it should be an attribute of something

Yeah I was using the context manager wrong there. I fixed that, and still cant add pictures twice using the context manager.

with napari.gui_qt():
                    self.viewer = napari.Viewer()
                    for key in response_meta.keys():
                        resp = requests.get(DATA_URL + '/data/binary/' + key)
                        image = np.frombuffer(resp.content, dtype=response_meta[key]["format"]).reshape(response_meta[key]['image_dimensions'])
                        return_image = np.array(image, dtype=np.uint8)
                        self.viewer.add_image(return_image, name=key)

to add pictures later on:

  with naprai.gui_qt():
                    self.viewer.add_image(return_image, name=resp["data_id"])

Ah, ok, so you’re trying to use a viewer instance created in one gui_qt() context in a different gui_qt context? If so, that’s the issue.

you can do this:

import napari
import numpy as np

with napari.gui_qt():
    viewer = napari.Viewer()
    viewer.add_image(np.random.rand(256, 256))

with napari.gui_qt():
    # note: this won't appear until after you close the first viewer
    viewer = napari.Viewer()
    viewer.add_image(np.random.rand(256, 256))

or this:

import napari
import numpy as np

with napari.gui_qt():
    viewer = napari.Viewer()
    viewer.add_image(np.random.rand(256, 256))
    # add_image again within the same context
    viewer.add_image(np.random.rand(256, 256))

but NOT this:

import napari
import numpy as np

with napari.gui_qt():
    viewer = napari.Viewer()
    viewer.add_image(np.random.rand(256, 256))

with napari.gui_qt():
    # ERROR the viewer from the last context is gone!
    viewer.add_image(np.random.rand(256, 256))

Let me step back and explain a little more about gui_qt, since it seems to be a common confusion:

napari, like a lot of python apps with GUIs, uses the Qt framework for it’s GUI elements. As such, it is necessary to have a qt “app” running before you instantiate a viewer… As you’ve probably seen, if you were to run this exact script:

import napari
import numpy as np

viewer = napari.view_image(np.random.rand(256, 256))

it wouldn’t work… you’d get an error saying RuntimeError: napari requires a Qt event loop to run… There are multiple ways to start a Qt application:

  1. Directly, using Qt:
    import napari
    import numpy as np
    from qtpy.QtWidgets import QApplication
    
    app = QApplication([])
    viewer = napari.view_image(np.random.rand(256, 256))
    app.exec_()
    
  2. Within an IPython or Jupyter Notebook session using the %gui qt magic
    In [1]: import napari
    In [2]: import numpy as np
    In [3]: %gui qt
    In [4]: viewer = napari.view_image(np.random.rand(256, 256))
    
  3. Using the napari.gui_qt() context manager as a convenience…
    import napari
    import numpy as np
    
    with napari.gui_qt():
        viewer = napari.view_image(np.random.rand(256, 256))
    

Note however, if you use the third option, you should not try to access anything created in one context from a different context. Consider the gui_qt() context like the “lifetime of the Qt application” … and each time you create a new context you’re starting a new Qt app. That’s one reason why I mentioned earlier that for more complex scenarios, it’s often better to start a single Qt application manually, for all of your needs (like option 1 here).

If you’re still running into issues, let me know the specific behavior (user interaction) you’re trying to achieve.

1 Like