1

I have built a GUI in Qt Creator that accepts some user input, performs some calculations, then updates some labels. Callbacks are used to update these labels as the user changes the various input text fields. If the user selects a checkbox, a simple plot is generated using the data calculated during a callback.

My problem is a new figure is generated each time the code runs via a callback. Ideally, the figure window would be static and I would just see my lineplot react to the user inputs as they are changed.

I have spent days trying everything my Google searches would return and none seem to work. I have tried:

How to update a plot in matplotlib?

How do I plot in real-time in a while loop using matplotlib?

and too many combinations of plt.ion(), plt.ioff(), plt.draw() etc. to no avail.

# --- START PLOT
        sns.set_theme(context="paper", style="darkgrid")
        sns.set_color_codes(palette='muted')

        fig, ax1 = plt.subplots(
            figsize=(
                10,
                6.18))  # plt.subplots is a function that returns a tuple containing a figure and axes object(s)

        # PC Plot creation
        # Create first y-axis (Efficiency)
        ax1.set_title('Project:  ' + project + '\n' + 'Turbine Performance Curve\n'
                      + 'D = ' + str(d) + 'm ' + 'RPM = ' + str(n) + ' ' + turb_description + '\n')
        ax1.set_xlabel('Flow (cms)', labelpad=5)
        ax1.set_ylabel('Efficiency (%)', labelpad=5)
        ax1 = sns.lineplot(x="Flow (cms)", y="Efficiency (%)", data=df1, color="steelblue", label='Efficiency',
                           legend=None, linewidth=2)

        # Create second y-axis (Power) and plot line
        ax2 = ax1.twinx()
        ax2.set_ylabel('Power (kW)', labelpad=15)
        ax2 = sns.lineplot(x="Flow (cms)", y="Power (kW)", data=df1, color="indianred", label='Output',
                           legend=None,
                           linewidth=2)

        # Add QDesign line
        sns.lineplot(x="Flow (cms)", y="Output (kW)", data=df3, color="grey", linewidth=2,
                     label='Qdesign' + ' = ' + str(q) + 'cms', legend=None)

        # Format grid lines
        ax2.grid(b=True, which='major', color='lightslategrey', linewidth=0.25)
        ax2.grid(b=True, which='minor', color='lightslategrey', linewidth=0.05)
        ax1.grid(b=True, which='major', color='lightslategrey', linewidth=0.25)
        ax1.grid(b=True, which='minor', color='lightslategrey', linewidth=0.05)

        # Set Axis limits
        ax1.set_xlim(q11minplot * h ** 0.5 * d * d * 0.5, qmaxplot)
        ax1.set_ylim(0, 100)
        ax2.set_ylim(bottom=0)

        # Add Legend
        fig.legend(loc=1, bbox_to_anchor=(0.94, 0.992))

        # Set second y axis grid same as first
        ax2.set_yticks(np.linspace(ax2.get_yticks()[0], ax2.get_yticks()[-1], len(ax1.get_yticks())))
        plt.minorticks_on()
        return plt

Is there a way, when I roll through this code again from a callback with an updated df1 dataframe, to just update the existing figure window instead of generating a new one.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
TyVan07
  • 11
  • 1
  • you're gonna want to use raw matplotlib for that. `ax.plot` returns the line artists, and you can update their x- and -y data dynamically – Paul H Dec 17 '20 at 00:34
  • Thanks Paul, are you able to elaborate a bit or perhaps provide a link on what you mean by 'raw' matplotlib? – TyVan07 Dec 17 '20 at 13:01
  • I mean using matplotlib functions and object methods instead of seaborn – Paul H Dec 17 '20 at 17:08
  • @PaulH can you provide an example as an answer. I am also having challenges implementing this. My bars do not get updated properly. – Maddenker Dec 05 '22 at 19:30
  • Have you checked the MPL website? Looks of object-oriented examples there – Paul H Dec 05 '22 at 19:46

0 Answers0