Forum Navigation
You need to log in to create posts and topics.

QWidget: Cannot create a QWidget without QApplication

I am trying to use matplotlib to plot a function, which will then be overlain on an animation I generate in Python using the ovito module. The code I have is as follows:

import ovito, PySide2
import matplotlib.pyplot as plt

def f(x):
    return x**2

def plot_f(args):
    """
    Plot the function f along the x axis.
    """
    x = [i for i in range(0, 385)]
    y = [f(x) for x in x]

    # define size of plot
    dpi = 80
    plot_width, plot_height = args.size[0], 0.1 * args.size[1]

    # create figure
    fig, ax = plt.subplots(figsize=(plot_width, plot_height), dpi=dpi)
    ax.plot(x, y)
    plt.title("f(x)")

    # render figure to buffer
    buf = fig.canvas.print_to_buffer()
    plt.close(fig)

    # Create a QImage from the memory buffer
    res_x, res_y = buf[1]
    img = PySide2.QtGui.QImage(buf[0], res_x, res_y, PySide2.QtGui.QImage.Format_RGBA8888)

    # Paint QImage onto viewport canvas
    args.painter.drawImage(0, 0, img)

vp = ovito.vis.Viewport()
vp.overlays.append(ovito.vis.PythonViewportOverlay(function = plot_f))
vp.render_anim("foo.gif")

This code is copied from that used to overlay matplotlib figures on Ovito animations, used in Example O2: Including data plots in rendered images, and has then been adapted to plot my function.

When I try to run this code, I get the following:

Warning: The scene to be rendered is empty. Did you forget to add a pipeline to the scene using Pipeline.add_to_scene()?
Output #0, gif, to 'foo.gif':
  Metadata:
    encoder         : Lavf58.29.100
    Stream #0:0: Video: gif, rgb8, 640x480, q=2-31, 10 fps, 100 tbn
QWidget: Cannot create a QWidget without QApplication

with the program quitting and not rendering an animation.

The warning is okay - in actuality I add files to my pipeline and do not get this warning. This warning is just associated with this minimal example.

What I do not understand is the last line 'QWidget: Cannot create a QWidget without QApplication'. What do I need to change in the above code to avoid this?

Hi,

Please test this, but you probably need to include the first two lines from the example script also in your script:

import matplotlib
matplotlib.use('Agg') # Activate 'agg' backend for off-screen plotting.

This tells matplotlib to use a different backend instead of the Qt backend, which it may be trying to activate by default. Both Ovito and the Qt backend of matplotlib use the Qt cross-platform framework, possibly different versions of it and different ways of initializing it. Since you imported the ovito module first, Ovito gets to initialize the Qt framework first. The Qt backend of matplotlib cannot work in this environment and bails out with the error message "QWidget: Cannot create a QWidget without QApplication".

Please let me know if switching to a different matplotlib backend doesn't solve the problem.

-Alex

Ah fantastic thank you, that works!

Seems to work irrespective of the order in which you import ovito or matplotlib as well, i.e.

import matplotlib
matplotlib.use('Agg')
import ovito

work just as well as:

import ovito
import matplotlib
matplotlib.use('Agg')

Thanks for the help, makes sense.

新的OVITO微信频道!
New for our users in China: OVITO on WeChat 

Official OVITO WeChat channel operated by Foshan Diesi Technology Co., Ltd.