NEW: added JKQTPlotterUpdateGuard guard class that prevents redrawing of a JKQTPlotter during the lifetime of a code block, improved documentation of speed during plot setup

This commit is contained in:
jkriege2 2025-01-15 22:24:20 +01:00
parent a275fb73c3
commit 2ad9b01aae
5 changed files with 139 additions and 6 deletions

View File

@ -124,11 +124,46 @@
representing objects by caling JKQTPlotter::getXAxis() or JKQTPlotter::getYAxis(). representing objects by caling JKQTPlotter::getXAxis() or JKQTPlotter::getYAxis().
</ol> </ol>
\see \ref JKQTPlotterSimpleTest and \see JKQTPlotterQtCreator \see \ref JKQTPlotterSimpleTest and \see \ref JKQTPlotterQtCreator
\defgroup jkqtplotter_general_usage_speedplotsetup Performance Considerations when Setting up Plots
Many of the function in JKQTPlotter case an immediate redraw of the widget. Examples are JKQTPlott::setX(),
JKQTPlotter::setY(), JKQTPlotter::setAbsoluteX(), JKQTPlotter::setAbsoluteY(), JKQTPlotter::addGraph() ...
so if you use a combination of these while setting up your plot, it is possible to
cause several (rather expensive) redraws of the plot widget. Therefore you can disable this redrawing, using
JKQTPlotter::setPlotUpdateEnabled() and you can explicitly cause a redraw with JKQTPlotter::redrawPlot().
To make this process even easier to use, there is a guard helper class for this: JKQTPlotterUpdateGuard.
Here is a code example:
\code
{
JKQTPlotterUpdateGuard guard(plotter);
// set up plot here, e.g.
plotter->setX();
plotter->setY(); ...
} // Block ends and immediate plot updates are reenabled. Also JKQTPlotter::redrawPlot() is called.
\endcode
This code has the same effect as the long version without the guard class shown below:
\code
const bool wasReplotEnabled=plotter->isPlotUpdateEnabled();
plotter->setPlotUpdateEnabled(false);
// set up plot here, e.g.
plotter->setX();
plotter->setY(); ...
// Setup ends and immediate plot updates are reenabled. Also JKQTPlotter::redrawPlot() is called.
plotter->setPlotUpdateEnabled(false);
if (wasReplotEnabled) plotter->redrawPlot();
\endcode
\see JKQTPlotter::setPlotUpdateEnabled(), JKQTPlotter::redrawPlot(), JKQTPlotterUpdateGuard
\defgroup jkqtplotter_general_usage_qtcreator How to use JKQTPlotter in the Qt Form Designer \defgroup jkqtplotter_general_usage_qtcreator How to use JKQTPlotter in the Qt Form Designer

View File

@ -141,6 +141,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>NEW: added JKQTPCoordinateAxis::setRangeFixed() which disables changing the axis range (and thus the zoom)</li> <li>NEW: added JKQTPCoordinateAxis::setRangeFixed() which disables changing the axis range (and thus the zoom)</li>
<li>NEW: added JKQTPCoordinateAxis::getMin() and JKQTPCoordinateAxis::getMax() getters</li> <li>NEW: added JKQTPCoordinateAxis::getMin() and JKQTPCoordinateAxis::getMax() getters</li>
<li>NEW: added example \ref JKQTPlotterUIScrollbar </li> <li>NEW: added example \ref JKQTPlotterUIScrollbar </li>
<li>NEW: added JKQTPlotterUpdateGuard guard class that prevents redrawing of a JKQTPlotter during the lifetime of a code block, improved documentation of speed during plot setup</li>
</ul></li> </ul></li>
<li>JKQTMathText:<ul> <li>JKQTMathText:<ul>

View File

@ -95,12 +95,12 @@ This test results in the following numbers (on my AMD Ryzen5 8/16-core laptop):
[comment]:RESULTS [comment]:RESULTS
<b>VERSION:</b> 5.0.0 <b>VERSION:</b> 5.0.0
<b>BUILD MODE:</b> Debug <b>BUILD MODE:</b> Release
<u><b>SERIAL RESULTS:</b></u><br/>runtime, overall = 7262.1ms<br/>single runtimes = (302.5 +/- 573.2) ms<br/>speedup = 1.00x<br/>threads / available = 1 / 16<br/><br/><br/> <u><b>SERIAL RESULTS:</b></u><br/>runtime, overall = 8283.1ms<br/>single runtimes = (345.0 +/- 957.8) ms<br/>speedup = 1.00x<br/>threads / available = 1 / 16<br/><br/><br/>
<u><b>PARALLEL RESULTS:</b></u><br/> <u><b>PARALLEL RESULTS:</b></u><br/>
runtime, overall = 896.4ms<br/>single runtimes = (259.4 +/- 55.2) ms<br/>speedup = 6.95x<br/>threads / available = 8 / 16<br/>batch runs = 3<br/><br/><b>speedup vs. serial = 8.1x</b> runtime, overall = 727.0ms<br/>single runtimes = (201.8 +/- 46.1) ms<br/>speedup = 6.66x<br/>threads / available = 8 / 16<br/>batch runs = 3<br/><br/><b>speedup vs. serial = 11.4x</b>
[comment]:RESULTS_END [comment]:RESULTS_END

View File

@ -2004,3 +2004,40 @@ void JKQTPlotter::MouseDragAction::clear()
modifier=Qt::NoModifier; modifier=Qt::NoModifier;
mouseButton=Qt::LeftButton; mouseButton=Qt::LeftButton;
} }
JKQTPlotterUpdateGuard::JKQTPlotterUpdateGuard(JKQTPlotter *plot, bool forceRedraw):
m_plot(plot), m_oldEnabled(true), m_forceRedraw(forceRedraw)
{
if (m_plot) {
m_oldEnabled=m_plot->isPlotUpdateEnabled();
m_plot->setPlotUpdateEnabled(false);
}
}
JKQTPlotterUpdateGuard::~JKQTPlotterUpdateGuard() {
release(m_forceRedraw);
}
JKQTPlotterUpdateGuard::JKQTPlotterUpdateGuard(JKQTPlotterUpdateGuard &&other):
m_plot(other.m_plot), m_oldEnabled(other.m_oldEnabled), m_forceRedraw(other.m_forceRedraw)
{
other.m_plot=nullptr;
}
JKQTPlotterUpdateGuard &JKQTPlotterUpdateGuard::operator=(JKQTPlotterUpdateGuard &&other) {
m_plot=other.m_plot;
m_oldEnabled=other.m_oldEnabled;
m_forceRedraw=other.m_forceRedraw;
other.m_plot=nullptr;
return *this;
}
void JKQTPlotterUpdateGuard::release(bool forceRedraw) {
if (m_plot) {
m_plot->setPlotUpdateEnabled(m_oldEnabled);
if (m_oldEnabled || forceRedraw) {
m_plot->redrawPlot();
}
}
m_plot=nullptr;
}

View File

@ -72,11 +72,21 @@ JKQTPLOTTER_LIB_EXPORT void initJKQTPlotterResources();
* \tableofcontents * \tableofcontents
* *
* *
*
*
* \section JKQTPLOTTER_BASICUSAGE Basic Usage of JKQTPlotter * \section JKQTPLOTTER_BASICUSAGE Basic Usage of JKQTPlotter
* *
* \copydetails jkqtplotter_general_usage_jkqtplotter * \copydetails jkqtplotter_general_usage_jkqtplotter
* *
* *
*
*
* \section JKQTPLOTTER_PERFORMACEWHILESETUP Performance Considerations when Setting up Plots
*
* \copydetails jkqtplotter_general_usage_speedplotsetup
*
*
*
* \section JKQTPLOTTER_SYNCMULTIPLOT Synchronizing Several Plots * \section JKQTPLOTTER_SYNCMULTIPLOT Synchronizing Several Plots
* *
* Often a single plot is not sufficient, but several plots need to be aligned with respect to each other: * Often a single plot is not sufficient, but several plots need to be aligned with respect to each other:
@ -637,7 +647,9 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPlotter: public QWidget {
bool isPlotUpdateEnabled() const; bool isPlotUpdateEnabled() const;
/** \brief sets whether automatic redrawing the plot is currently activated (e.g. you can sett his to \c false while performing major updates on the plot) /** \brief sets whether automatic redrawing the plot is currently activated (e.g. you can sett his to \c false while performing major updates on the plot)
* *
* \see isPlotUpdateEnabled() * \see JKQTPlotterUpdateGuard for a guard class coupling calls to setPlotUpdateEnabled() and redrawPlot() with the lifetime of a code block.
* See \ref jkqtplotter_general_usage_speedplotsetup for a detailed description.
* Also see isPlotUpdateEnabled().
*/ */
void setPlotUpdateEnabled(bool enable); void setPlotUpdateEnabled(bool enable);
@ -1397,7 +1409,9 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPlotter: public QWidget {
/** \brief indicates whether the plot is updated automatically at the moment /** \brief indicates whether the plot is updated automatically at the moment
* *
* \see setPlotUpdateEnabled(), isPlotUpdateEnabled() * \see setPlotUpdateEnabled(), isPlotUpdateEnabled(),
* JKQTPlotterUpdateGuard for a guard class coupling calls to setPlotUpdateEnabled() and redrawPlot() with the lifetime of a code block.
* See \ref jkqtplotter_general_usage_speedplotsetup for a detailed description.
*/ */
bool doDrawing; bool doDrawing;
@ -1711,6 +1725,52 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPlotter: public QWidget {
}; };
/** \brief Guard Class (RAII construct) for JKQTPlotter that disables replotting on construction and reenables it on destruction
* \ingroup jkqtpplotterclasses
*
* This class can be used to forbid replotting (to improve performance) while setting up a plot.
* The redraw is called on destruction of the guard,i.e. typically when leaving the block that
* encapsulates the plot construction.
*
* \code
* {
* JKQTPlotterUpdateGuard guard(plotter);
*
* // set up plot here, e.g.
* plotter->setX();
* plotter->setY(); ...
* } // Block ends and immediate plot updates are reenabled. Also JKQTPlotter::redrawPlot() is called.
* \endcode
*
* \see JKQTPlotter::setPlotUpdateEnabled(), JKQTPlotter::redrawPlot()
* \see JKQTPlotterUpdateGuard for a guard class coupling calls to setPlotUpdateEnabled() and redrawPlot() with the lifetime of a code block.
* See \ref jkqtplotter_general_usage_speedplotsetup for a detailed description.
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPlotterUpdateGuard {
public:
JKQTPlotterUpdateGuard(JKQTPlotter* plot, bool forceRedraw=false);
~JKQTPlotterUpdateGuard();
JKQTPlotterUpdateGuard(const JKQTPlotterUpdateGuard&)=delete;
JKQTPlotterUpdateGuard& operator=(const JKQTPlotterUpdateGuard&)=delete;
JKQTPlotterUpdateGuard(JKQTPlotterUpdateGuard&& other);
JKQTPlotterUpdateGuard& operator=(JKQTPlotterUpdateGuard&& other);
/** \brief release the lock, if \a forceRedraw equals \c true JKQTPlotter::redrawPlot() is called in any case,
* if it is \c false, JKQTPlotter::redrawPlot() is called only if JKQTPlotter::isPlotUpdateEnabled() was \c true
* on construction of the guard */
void release(bool forceRedraw=false);
private:
JKQTPlotter* m_plot;
bool m_oldEnabled;
bool m_forceRedraw;
};
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
/** \brief qHash-variant used by JKQTPlotter /** \brief qHash-variant used by JKQTPlotter