NEW: you can provide a custom draw functor to barcharts to completely customize their look

This commit is contained in:
jkriege2 2022-10-28 21:48:42 +02:00
parent d59f5e6692
commit 972bc6c1e0
25 changed files with 390 additions and 25 deletions

View File

@ -144,6 +144,7 @@ if(JKQtPlotter_BUILD_EXAMPLES)
barchart_twocolor/barchart_twocolor,barchart_twocolor_hor barchart_twocolor/barchart_twocolor,barchart_twocolor_hor
barchart_errorbars/barchart_errorbars,barchart_errorbars_hor barchart_errorbars/barchart_errorbars,barchart_errorbars_hor
barchart_functorfill/barchart_functorfill,barchart_functorfill_hor barchart_functorfill/barchart_functorfill,barchart_functorfill_hor
barchart_customdrawfunctor/barchart_customdrawfunctor,barchart_customdrawfunctor_hor
wiggleplots/wiggleplot_x,wiggleplot_y wiggleplots/wiggleplot_x,wiggleplot_y
advplotstyling/advancedlineandfillstyling advplotstyling/advancedlineandfillstyling
boxplot boxplot
@ -196,6 +197,7 @@ if(JKQtPlotter_BUILD_EXAMPLES)
barchart_twocolor/JKQTPBarVerticalGraphTwoColorFilling,JKQTPBarHorizontalGraphTwoColorFilling/--smallscreenshotplot barchart_twocolor/JKQTPBarVerticalGraphTwoColorFilling,JKQTPBarHorizontalGraphTwoColorFilling/--smallscreenshotplot
barchart_errorbars/JKQTPBarVerticalErrorGraph,JKQTPBarHorizontalErrorGraph/--smallscreenshotplot barchart_errorbars/JKQTPBarVerticalErrorGraph,JKQTPBarHorizontalErrorGraph/--smallscreenshotplot
barchart_functorfill/JKQTPBarVerticalGraphFunctorFilling,JKQTPBarHorizontalGraphFunctorFilling/--smallscreenshotplot barchart_functorfill/JKQTPBarVerticalGraphFunctorFilling,JKQTPBarHorizontalGraphFunctorFilling/--smallscreenshotplot
barchart_customdrawfunctor/JKQTPBarVerticalGraphCustomDrawFunctor,JKQTPBarHorizontalGraphCustomDrawFunctor/--smallscreenshotplot
wiggleplots/JKQTPFilledCurveXGraph_wiggle,JKQTPFilledCurveYGraph_wiggle wiggleplots/JKQTPFilledCurveXGraph_wiggle,JKQTPFilledCurveYGraph_wiggle
contourplot/JKQTPColumnContourPlot/--smallscreenshotplot contourplot/JKQTPColumnContourPlot/--smallscreenshotplot
filledgraphs/JKQTPFilledCurveXGraph,JKQTPFilledCurveYGraph/--smallscreenshotplot filledgraphs/JKQTPFilledCurveXGraph,JKQTPFilledCurveYGraph/--smallscreenshotplot

View File

@ -46,9 +46,12 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
<tr><td> \image html barchart_twocolor_small.png <tr><td> \image html barchart_twocolor_small.png
<td> \subpage JKQTPlotterBarchartsTwoColorFilling <td> \subpage JKQTPlotterBarchartsTwoColorFilling
<td> `JKQTPBarVerticalGraph` <br> JKQTPDatastore::addColumnCalculatedFromColumn() <td> `JKQTPBarVerticalGraph` <br> JKQTPDatastore::addColumnCalculatedFromColumn()
<tr><td> \image html barchart_functorfill_small.png <tr><td> \image html barchart_customdrawfunctor_small.png
<td> \subpage JKQTPlotterBarchartsFunctorFilling <td> \subpage JKQTPlotterBarchartsFunctorFilling
<td> `JKQTPBarVerticalGraph` <br> JKQTPDatastore::addColumnCalculatedFromColumn() <td> `JKQTPBarVerticalGraph` <br> JKQTPDatastore::addColumnCalculatedFromColumn()
<tr><td> \image html barchart_functorfill_small.png
<td> \subpage JKQTPlotterBarchartsCustomDrawFunctor
<td> `JKQTPBarVerticalGraph` <br> JKQTPDatastore::addColumnCalculatedFromColumn()
<tr><td> \image html stackedbars_small.png <tr><td> \image html stackedbars_small.png
<td> \subpage JKQTPlotterStackedBarChart <td> \subpage JKQTPlotterStackedBarChart
<td> `JKQTPBarVerticalStackableGraph`, `JKQTPBarHorizontalStackableGraph` <br> C++-style vectors of data <td> `JKQTPBarVerticalStackableGraph`, `JKQTPBarHorizontalStackableGraph` <br> C++-style vectors of data

View File

@ -26,7 +26,7 @@ This page lists several todos and wishes for future version of JKQTPlotter
<li>plot: elongated grid to left of tick labels</li> <li>plot: elongated grid to left of tick labels</li>
<li>plot: legend positioning as combination of 3 values: inside|outside + left|center|right + top|vcenter|bottom</li> <li>plot: legend positioning as combination of 3 values: inside|outside + left|center|right + top|vcenter|bottom</li>
<li>plot: refactor print preview/export preview code </li> <li>plot: refactor print preview/export preview code </li>
<li>plot: reqork layouting of legends: there are some inconsistencies/too large gaps ...</li> <li>plot: rework layouting of legends: there are some inconsistencies/too large gaps ...</li>
<li>plot: secondary axes: independent and dependent (i.e. with transformation function from primary axis)</li> <li>plot: secondary axes: independent and dependent (i.e. with transformation function from primary axis)</li>
<li>sryling: better styling/more styling options for data-tooltips</li> <li>sryling: better styling/more styling options for data-tooltips</li>
<li>styling: color gradients as fill-styles in style-INIs</li> <li>styling: color gradients as fill-styles in style-INIs</li>

View File

@ -64,6 +64,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>NEW: barcharts (derived from JKQTPBarGraphBase) can be configured to use different fill styles above and below the baseline, see JKQTPBarGraphBase::FillMode </li> <li>NEW: barcharts (derived from JKQTPBarGraphBase) can be configured to use different fill styles above and below the baseline, see JKQTPBarGraphBase::FillMode </li>
<li>NEW: barcharts may have rounded corners now, via JKQTPBarGraphBase::setRectRadius()</li> <li>NEW: barcharts may have rounded corners now, via JKQTPBarGraphBase::setRectRadius()</li>
<li>NEW: barcharts can be colored by a user-specified functor</li> <li>NEW: barcharts can be colored by a user-specified functor</li>
<li>NEW: you can provide a custom draw functor to barcharts to completely customize their look</li>
</ul></li> </ul></li>
<li>JKQTMathText:<ul> <li>JKQTMathText:<ul>

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -51,6 +51,7 @@ add_subdirectory(boxplot)
add_subdirectory(barchart_errorbars) add_subdirectory(barchart_errorbars)
add_subdirectory(barchart_functorfill) add_subdirectory(barchart_functorfill)
add_subdirectory(barchart_twocolor) add_subdirectory(barchart_twocolor)
add_subdirectory(barchart_customdrawfunctor)
add_subdirectory(contourplot) add_subdirectory(contourplot)
add_subdirectory(datastore) add_subdirectory(datastore)
add_subdirectory(datastore_groupedstat) add_subdirectory(datastore_groupedstat)

View File

@ -0,0 +1,34 @@
cmake_minimum_required(VERSION 3.16)
set(EXAMPLE_NAME barchart_customdrawfunctor)
set(EXENAME jkqtptest_${EXAMPLE_NAME})
message( STATUS ".. Building Example ${EXAMPLE_NAME}" )
# Set up source files
set(SOURCES barchart_customdrawfunctor.cpp )
set(HEADERS )
set(RESOURCES )
set(UIS )
add_executable(${EXENAME} WIN32 ${SOURCES} ${HEADERS} ${RESOURCES} ${UIS})
target_link_libraries(${EXENAME} JKQTPExampleToolsLib)
target_include_directories(${EXENAME} PRIVATE ../../lib)
if(JKQtPlotter_BUILD_STATIC_LIBS)
target_link_libraries(${EXENAME} JKQTPlotterLib)
elseif(JKQtPlotter_BUILD_SHARED_LIBS)
target_link_libraries(${EXENAME} JKQTPlotterSharedLib)
endif()
# precomiled headers to speed up compilation
if (JKQtPlotter_BUILD_WITH_PRECOMPILED_HEADERS)
target_precompile_headers(${EXENAME} REUSE_FROM jkqtptest_simpletest)
endif (JKQtPlotter_BUILD_WITH_PRECOMPILED_HEADERS)
# Installation
install(TARGETS ${EXENAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
#Installation of Qt DLLs on Windows
jkqtplotter_deployqt(${EXENAME})

View File

@ -0,0 +1,89 @@
# Example (JKQTPlotter): Barchart With Custom Draw Functor {#JKQTPlotterBarchartsCustomDrawFunctor}
This project (see [`barchart_customdrawfunctor`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/barchart_customdrawfunctor) shows how to draw customized barcharts, with a custom draw functor.
The source code of the main application is (see [`barchart_customdrawfunctor.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/barchart_customdrawfunctor/barchart_customdrawfunctor.cpp):
```.cpp
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
JKQTPDatastore* ds=plot.getDatastore();
// 2. now we create two columns for key and value
size_t columnK=ds->addLinearColumn(7, 0, 6, "k");
size_t columnV=ds->addColumnCalculatedFromColumn(columnK, [](double x) { return jkqtp_sign(2.0*x-2.5)*qMax(2.0,fabs(2.0*x-2.5)); }, "v");
// 3. load a stylesheet
plot.loadCurrentPlotterStyle(QSettings(":/JKQTPlotter/styles/seaborn.ini", QSettings::IniFormat));
// 4. create graph in the plot, which plots the dataset:
JKQTPBarVerticalGraph* graph=new JKQTPBarVerticalGraph(&plot);
graph->setKeyColumn(columnK);
graph->setValueColumn(columnV);
// this is the custom draw functor
graph->setCustomDrawingFunctor(
[](JKQTPEnhancedPainter& painter, const QRectF& bar_px, const QPointF& datapoint, Qt::Orientation orientation, JKQTPBarGraphBase* graph) {
painter.save();
painter.setPen(Qt::NoPen);
QBrush b=painter.brush();
QBrush bDeco=b;
bDeco.setColor(b.color().lighter());
// we draw the bar with a rounded end and add a lightly colored circle near the top
if (orientation==Qt::Vertical) {
// for vertical barcharts
const double dx=bar_px.width()/2.0;
const double r=dx*0.85;
// depending in whether the bar elongates above or below the baseline,
// we have to align the circle wrt the top or the bottom of the rectangle bar_px
if (datapoint.y()>=graph->getBaseline()) {
painter.drawComplexRoundedRect(bar_px, dx, dx, 0, 0, Qt::AbsoluteSize);
painter.setBrush(bDeco);
painter.drawEllipse(QPointF(bar_px.center().x(), bar_px.top()+dx), r,r);
} else {
painter.drawComplexRoundedRect(bar_px, 0, 0, dx, dx, Qt::AbsoluteSize);
painter.setBrush(bDeco);
painter.drawEllipse(QPointF(bar_px.center().x(), bar_px.bottom()-dx), r,r);
}
} else {
// for horizontal barcharts
const double dx=bar_px.height()/2.0;
const double r=dx*0.85;
if (datapoint.x()>=graph->getBaseline()) {
painter.drawComplexRoundedRect(bar_px, 0, dx, 0, dx, Qt::AbsoluteSize);
painter.setBrush(bDeco);
painter.drawEllipse(QPointF(bar_px.right()-dx, bar_px.center().y()), r,r);
} else {
painter.drawComplexRoundedRect(bar_px, dx,0,dx,0, Qt::AbsoluteSize);
painter.setBrush(bDeco);
painter.drawEllipse(QPointF(bar_px.left()+dx, bar_px.center().y()), r,r);
}
}
painter.restore();
}
);
// enable usage of cutom draw functor
graph->setUseCustomDrawFunctor(true);
// set graph color
graph->setColor(QColor("blue"));
plot.addGraph(graph);
// 5. autoscale the plot so the graph is contained
plot.zoomToFit();
// 6. show plotter and make it a decent size
plot.setWindowTitle(title);
plot.show();
plot.resize(400,400);
```
The result looks like this:
![barchart_customdrawfunctor](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/barchart_customdrawfunctor.png)
In order to draw horizontal error bars, you have to use `JKQTPBarHorizontalGraph` instead of `JKQTPBarVerticalGraph`. The functor given above also covers that case by checking the parameter `orientation`:
![barchart_customdrawfunctor_hor](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/barchart_customdrawfunctor_hor.png)

View File

@ -0,0 +1,102 @@
/** \example barchart_functorfill.cpp
* Shows how to draw Barcharts with colors defined by a functor JKQTPlotter
*
* \ref JKQTPlotterBarchartsFunctorFilling
*/
#include "jkqtpexampleapplication.h"
#include <QApplication>
#include "jkqtplotter/jkqtplotter.h"
#include "jkqtplotter/graphs/jkqtpbarchart.h"
#include "jkqtcommon/jkqtpmathtools.h"
#include "jkqtpexampleapplication.h"
template <class TCHART>
void doExample(JKQTPlotter& plot, const QString& title)
{
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
JKQTPDatastore* ds=plot.getDatastore();
// 2. now we create two columns for key and value
size_t columnK=ds->addLinearColumn(7, 0, 6, "k");
size_t columnV=ds->addColumnCalculatedFromColumn(columnK, [](double x) { return jkqtp_sign(2.0*x-2.5)*qMax(2.0,fabs(2.0*x-2.5)); }, "v");
// 3. load a stylesheet
plot.loadCurrentPlotterStyle(QSettings(":/JKQTPlotter/styles/seaborn.ini", QSettings::IniFormat));
// 4. create graph in the plot, which plots the dataset:
JKQTPBarGraphBase* graph=new TCHART(&plot);
graph->setKeyColumn(columnK);
graph->setValueColumn(columnV);
// this is the custom draw functor
graph->setCustomDrawingFunctor(
[](JKQTPEnhancedPainter& painter, const QRectF& bar_px, const QPointF& datapoint, Qt::Orientation orientation, JKQTPBarGraphBase* graph) {
painter.save();
painter.setPen(Qt::NoPen);
QBrush b=painter.brush();
QBrush bDeco=b;
bDeco.setColor(b.color().lighter());
// we draw the bar with a rounded end and add a lightly colored circle near the top
if (orientation==Qt::Vertical) {
// for vertical barcharts
const double dx=bar_px.width()/2.0;
const double r=dx*0.85;
// depending in whether the bar elongates above or below the baseline,
// we have to align the circle wrt the top or the bottom of the rectangle bar_px
if (datapoint.y()>=graph->getBaseline()) {
painter.drawComplexRoundedRect(bar_px, dx, dx, 0, 0, Qt::AbsoluteSize);
painter.setBrush(bDeco);
painter.drawEllipse(QPointF(bar_px.center().x(), bar_px.top()+dx), r,r);
} else {
painter.drawComplexRoundedRect(bar_px, 0, 0, dx, dx, Qt::AbsoluteSize);
painter.setBrush(bDeco);
painter.drawEllipse(QPointF(bar_px.center().x(), bar_px.bottom()-dx), r,r);
}
} else {
// for horizontal barcharts
const double dx=bar_px.height()/2.0;
const double r=dx*0.85;
if (datapoint.x()>=graph->getBaseline()) {
painter.drawComplexRoundedRect(bar_px, 0, dx, 0, dx, Qt::AbsoluteSize);
painter.setBrush(bDeco);
painter.drawEllipse(QPointF(bar_px.right()-dx, bar_px.center().y()), r,r);
} else {
painter.drawComplexRoundedRect(bar_px, dx,0,dx,0, Qt::AbsoluteSize);
painter.setBrush(bDeco);
painter.drawEllipse(QPointF(bar_px.left()+dx, bar_px.center().y()), r,r);
}
}
painter.restore();
}
);
// enable usage of cutom draw functor
graph->setUseCustomDrawFunctor(true);
// set graph color
graph->setColor(QColor("blue"));
plot.addGraph(graph);
// 5. autoscale the plot so the graph is contained
plot.zoomToFit();
// 6. show plotter and make it a decent size
plot.setWindowTitle(title);
plot.show();
plot.resize(400,400);
}
int main(int argc, char* argv[])
{
JKQTPAppSettingController highDPIController(argc,argv);
JKQTPExampleApplication app(argc, argv);
JKQTPlotter plotV, plotH;
doExample<JKQTPBarVerticalGraph>(plotV, "1: JKQTPBarVerticalGraph");
doExample<JKQTPBarHorizontalGraph>(plotH, "2: JKQTPBarHorizontalGraph");
return app.exec();
}

View File

@ -11,7 +11,7 @@ The source code of the main application is (see [`barchart_functorfill.cpp`](htt
size_t columnV=ds->addColumnCalculatedFromColumn(columnK, [](double x) { return 5.0+x; }, "v"); size_t columnV=ds->addColumnCalculatedFromColumn(columnK, [](double x) { return 5.0+x; }, "v");
// 3. create graph in the plot, which plots the dataset: // 3. create graph in the plot, which plots the dataset:
JKQTPBarGraphBase* graph=new TCHART(&plot); JKQTPBarVerticalGraph* graph=new JKQTPBarVerticalGraph(&plot);
graph->setKeyColumn(columnK); graph->setKeyColumn(columnK);
graph->setValueColumn(columnV); graph->setValueColumn(columnV);
// set FunctorFilling fill Mode // set FunctorFilling fill Mode

View File

@ -121,21 +121,26 @@ void JKQTPBarVerticalGraph::draw(JKQTPEnhancedPainter& painter) {
painter.setPen(p); painter.setPen(p);
} }
const QRectF r(QPointF(x, y), QPointF(xx, yy)); const QRectF r(QPointF(x, y), QPointF(xx, yy));
const double rAtBaseline=parent->pt2px(painter, rectRadiusAtBaseline); if (usesCustomDrawFunctor()) {
const double rAtValue=parent->pt2px(painter, rectRadiusAtValue); if (m_customDrawFunctor) {
//qDebug()<<"r="<<r<<", rectRadiusAtBaseline="<<rectRadiusAtBaseline<<", rectRadiusAtValue="<<rectRadiusAtValue<<", rAtBaseline="<<rAtBaseline<<", rAtValue="<<rAtValue; m_customDrawFunctor(painter, r, QPointF(xv,yv), Qt::Vertical, this);
if (rAtBaseline+rAtValue>=r.height()+2) { }
//qDebug()<<"drawRect";
painter.drawRect(r);
} else { } else {
//qDebug()<<"drawRoundRect swapped="<<swapped; const double rAtBaseline=parent->pt2px(painter, rectRadiusAtBaseline);
if (swapped) { const double rAtValue=parent->pt2px(painter, rectRadiusAtValue);
painter.drawComplexRoundedRect(r,rAtBaseline,rAtBaseline,rAtValue,rAtValue,Qt::AbsoluteSize); //qDebug()<<"r="<<r<<", rectRadiusAtBaseline="<<rectRadiusAtBaseline<<", rectRadiusAtValue="<<rectRadiusAtValue<<", rAtBaseline="<<rAtBaseline<<", rAtValue="<<rAtValue;
if (rAtBaseline+rAtValue>=r.height()+2) {
//qDebug()<<"drawRect";
painter.drawRect(r);
} else { } else {
painter.drawComplexRoundedRect(r,rAtValue,rAtValue,rAtBaseline,rAtBaseline,Qt::AbsoluteSize); //qDebug()<<"drawRoundRect swapped="<<swapped;
if (swapped) {
painter.drawComplexRoundedRect(r,rAtBaseline,rAtBaseline,rAtValue,rAtValue,Qt::AbsoluteSize);
} else {
painter.drawComplexRoundedRect(r,rAtValue,rAtValue,rAtBaseline,rAtBaseline,Qt::AbsoluteSize);
}
} }
} }
} }
} }
} }
@ -283,17 +288,24 @@ void JKQTPBarHorizontalGraph::draw(JKQTPEnhancedPainter& painter) {
painter.setPen(p); painter.setPen(p);
} }
const QRectF r(QPointF(x, y), QPointF(xx, yy)); const QRectF r(QPointF(x, y), QPointF(xx, yy));
const double rAtBaseline=parent->pt2px(painter, rectRadiusAtBaseline); if (usesCustomDrawFunctor()) {
const double rAtValue=parent->pt2px(painter, rectRadiusAtBaseline); if (m_customDrawFunctor) {
if (rAtBaseline+rAtValue>r.width()+2) { m_customDrawFunctor(painter, r, QPointF(xv,yv), Qt::Horizontal, this);
painter.drawRect(r);
} else {
if (swapped) {
painter.drawComplexRoundedRect(r,rAtBaseline,rAtValue,rAtBaseline,rAtValue,Qt::AbsoluteSize);
} else {
painter.drawComplexRoundedRect(r,rAtValue,rAtBaseline,rAtValue,rAtBaseline,Qt::AbsoluteSize);
} }
} } } else {
const double rAtBaseline=parent->pt2px(painter, rectRadiusAtBaseline);
const double rAtValue=parent->pt2px(painter, rectRadiusAtBaseline);
if (rAtBaseline+rAtValue>r.width()+2) {
painter.drawRect(r);
} else {
if (swapped) {
painter.drawComplexRoundedRect(r,rAtBaseline,rAtValue,rAtBaseline,rAtValue,Qt::AbsoluteSize);
} else {
painter.drawComplexRoundedRect(r,rAtValue,rAtBaseline,rAtValue,rAtBaseline,Qt::AbsoluteSize);
}
}
}
}
} }
} }
} }

View File

@ -71,6 +71,26 @@
\image html JKQTPBarVerticalGraphFunctorFilling.png \image html JKQTPBarVerticalGraphFunctorFilling.png
You can also completely customize the drawing by defining a custom draw functor:
\code
graph->setCustomDrawingFunctor(
[](JKQTPEnhancedPainter& painter, const QRectF& bar_px, const QPointF& datapoint, Qt::Orientation orientation, JKQTPBarGraphBase* graph) {
// draw the bar (if required), pen and brush are already set properly
painter.drawRect(bar_px);
// now we can add some decoration or replace the instruction above:
// ........
}
);
// enable usage of cutom draw functor
graph->setUseCustomDrawFunctor(true);
\endcode
See \ref JKQTPlotterBarchartsCustomDrawFunctor for a detailed example.
The result may look like this:
\image html JKQTPBarVerticalGraphCustomDrawFunctor.png
\see JKQTPBarHorizontalGraph, \ref JKQTPlotterBarcharts, jkqtpstatAddHHistogram1D(), jkqtpstatAddHHistogram1DAutoranged() \see JKQTPBarHorizontalGraph, \ref JKQTPlotterBarcharts, jkqtpstatAddHHistogram1D(), jkqtpstatAddHHistogram1DAutoranged()
*/ */
class JKQTPLOTTER_LIB_EXPORT JKQTPBarVerticalGraph: public JKQTPBarGraphBase { class JKQTPLOTTER_LIB_EXPORT JKQTPBarVerticalGraph: public JKQTPBarGraphBase {
@ -190,6 +210,24 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarVerticalErrorGraph: public JKQTPBarVertical
\image html JKQTPBarHorizontalGraphFunctorFilling.png \image html JKQTPBarHorizontalGraphFunctorFilling.png
You can also completely customize the drawing by defining a custom draw functor:
\code
graph->setCustomDrawingFunctor(
[](JKQTPEnhancedPainter& painter, const QRectF& bar_px, const QPointF& datapoint, Qt::Orientation orientation, JKQTPBarGraphBase* graph) {
// draw the bar (if required), pen and brush are already set properly
painter.drawRect(bar_px);
// now we can add some decoration or replace the instruction above:
// ........
}
);
// enable usage of cutom draw functor
graph->setUseCustomDrawFunctor(true);
\endcode
See \ref JKQTPlotterBarchartsCustomDrawFunctor for a detailed example.
The result may look like this:
\image html JKQTPBarHorizontalGraphCustomDrawFunctor.png
\see \ref JKQTPlotterBarcharts, jkqtpstatAddVHistogram1D(), jkqtpstatAddVHistogram1DAutoranged() \see \ref JKQTPlotterBarcharts, jkqtpstatAddVHistogram1D(), jkqtpstatAddVHistogram1DAutoranged()
*/ */

View File

@ -38,6 +38,7 @@ JKQTPBarGraphBase::JKQTPBarGraphBase(JKQTBasePlotter* parent):
JKQTPXYBaselineGraph(parent), JKQTPXYBaselineGraph(parent),
width(0.9), shift(0), width(0.9), shift(0),
m_fillMode(FillMode::SingleFilling), m_fillMode(FillMode::SingleFilling),
m_useCustomDrawFunctor(false),
m_lineColorDerivationModeForSpecialFill(parent->getCurrentPlotterStyle().graphsStyle.barchartStyle.graphColorDerivationMode), m_lineColorDerivationModeForSpecialFill(parent->getCurrentPlotterStyle().graphsStyle.barchartStyle.graphColorDerivationMode),
rectRadiusAtBaseline(0),rectRadiusAtValue(0) rectRadiusAtBaseline(0),rectRadiusAtValue(0)
{ {
@ -57,7 +58,6 @@ JKQTPBarGraphBase::JKQTPBarGraphBase(JKQTPlotter* parent):
void JKQTPBarGraphBase::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) { void JKQTPBarGraphBase::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen p=getLinePenForRects(painter, parent); QPen p=getLinePenForRects(painter, parent);
QPen np(Qt::NoPen);
QBrush b=getFillBrush(painter, parent); QBrush b=getFillBrush(painter, parent);
//int y=rect.top()+rect.height()/2.0; //int y=rect.top()+rect.height()/2.0;
painter.setPen(p); painter.setPen(p);
@ -242,6 +242,21 @@ void JKQTPBarGraphBase::setFillBrushFunctor(SimpleFillBrushFunctor &&f) {
m_fillBrushFunctor=SimpleFillBrushFunctorAdaptor(std::forward<SimpleFillBrushFunctor>(f)); m_fillBrushFunctor=SimpleFillBrushFunctorAdaptor(std::forward<SimpleFillBrushFunctor>(f));
} }
void JKQTPBarGraphBase::setCustomDrawingFunctor(CustomDrawingFunctor &&f)
{
m_customDrawFunctor=std::forward<CustomDrawingFunctor>(f);
}
void JKQTPBarGraphBase::setCustomDrawingFunctor(const CustomDrawingFunctor &f)
{
m_customDrawFunctor=f;
}
void JKQTPBarGraphBase::setUseCustomDrawFunctor(bool enabled)
{
m_useCustomDrawFunctor=enabled;
}
double JKQTPBarGraphBase::getParentStackedMax(int /*index*/) const double JKQTPBarGraphBase::getParentStackedMax(int /*index*/) const
{ {
return getBaseline(); return getBaseline();
@ -383,3 +398,8 @@ JKQTPColorDerivationMode JKQTPBarGraphBase::getLineColorDerivationModeForSpecial
{ {
return m_lineColorDerivationModeForSpecialFill; return m_lineColorDerivationModeForSpecialFill;
} }
bool JKQTPBarGraphBase::usesCustomDrawFunctor() const
{
return m_useCustomDrawFunctor;
}

View File

@ -67,6 +67,27 @@
* The result may look like this: * The result may look like this:
* *
* \image html JKQTPBarVerticalGraphFunctorFilling.png * \image html JKQTPBarVerticalGraphFunctorFilling.png
*
* You can also completely customize the drawing by defining a custom draw functor:
* \code
* graph->setCustomDrawingFunctor(
* [](JKQTPEnhancedPainter& painter, const QRectF& bar_px, const QPointF& datapoint, Qt::Orientation orientation, JKQTPBarGraphBase* graph) {
* // draw the bar (if required), pen and brush are already set properly
* painter.drawRect(bar_px);
* // now we can add some decoration or replace the instruction above:
* // ........
* }
* );
* // enable usage of cutom draw functor
* graph->setUseCustomDrawFunctor(true);
* \endcode
*
* See \ref JKQTPlotterBarchartsCustomDrawFunctor for a detailed example.
*
* The result may look like this:
*
* \image html JKQTPBarVerticalGraphCustomDrawFunctor.png
* *
* \see JKQTPBarHorizontalGraph, JKQTPBarVerticalGraph * \see JKQTPBarHorizontalGraph, JKQTPBarVerticalGraph
*/ */
@ -83,6 +104,9 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarGraphBase: public JKQTPXYBaselineGraph, pub
* \see setFillBrushFunctor(), getFillBrushFunctor() * \see setFillBrushFunctor(), getFillBrushFunctor()
*/ */
typedef std::function<QBrush(double key, double value)> SimpleFillBrushFunctor; typedef std::function<QBrush(double key, double value)> SimpleFillBrushFunctor;
/** \brief functor for custom drawing of bars */
typedef std::function<void(JKQTPEnhancedPainter& painter, const QRectF& bar_px, const QPointF& datapoint, Qt::Orientation orientation, JKQTPBarGraphBase* graph)> CustomDrawingFunctor;
/** \brief specifies how the area below the graph is filled /** \brief specifies how the area below the graph is filled
* *
* \see setFillMode(), getFillMode(), fillStyleBelow(), \ref JKQTPlotterWigglePlots * \see setFillMode(), getFillMode(), fillStyleBelow(), \ref JKQTPlotterWigglePlots
@ -137,6 +161,8 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarGraphBase: public JKQTPXYBaselineGraph, pub
const FillBrushFunctor& getFillBrushFunctor() const; const FillBrushFunctor& getFillBrushFunctor() const;
/** \copydoc m_lineColorDerivationModeForSpecialFill */ /** \copydoc m_lineColorDerivationModeForSpecialFill */
JKQTPColorDerivationMode getLineColorDerivationModeForSpecialFill() const; JKQTPColorDerivationMode getLineColorDerivationModeForSpecialFill() const;
/** \copydoc m_useCustomDrawFunctor */
bool usesCustomDrawFunctor() const;
public slots: public slots:
/** \copydoc m_fillMode */ /** \copydoc m_fillMode */
@ -152,6 +178,13 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarGraphBase: public JKQTPXYBaselineGraph, pub
/** \copydoc m_fillBrushFunctor */ /** \copydoc m_fillBrushFunctor */
void setFillBrushFunctor(JKQTPBarGraphBase::SimpleFillBrushFunctor&& f); void setFillBrushFunctor(JKQTPBarGraphBase::SimpleFillBrushFunctor&& f);
/** \copydoc m_customDrawFunctor */
void setCustomDrawingFunctor(JKQTPBarGraphBase::CustomDrawingFunctor&& f);
/** \copydoc m_customDrawFunctor */
void setCustomDrawingFunctor(const JKQTPBarGraphBase::CustomDrawingFunctor& f);
/** \copydoc m_useCustomDrawFunctor */
void setUseCustomDrawFunctor(bool enabled);
/** \brief finds all bar charts of the same orientation and determines width and shift, so they stand side by side /** \brief finds all bar charts of the same orientation and determines width and shift, so they stand side by side
* *
* \param maxWidth the maximum (relative) width, that all bars will span of the (doubled) inter-bar distance * \param maxWidth the maximum (relative) width, that all bars will span of the (doubled) inter-bar distance
@ -263,6 +296,36 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarGraphBase: public JKQTPXYBaselineGraph, pub
* \see setFillBrushFunctor(), getFillBrushFunctor(), m_fillMode * \see setFillBrushFunctor(), getFillBrushFunctor(), m_fillMode
*/ */
FillBrushFunctor m_fillBrushFunctor; FillBrushFunctor m_fillBrushFunctor;
/** \brief this allows to provide custom drawing code for the bars.
* It is called for every visible bar if activated by \c setUseCustomDrawFunctor(true) .
*
* Here is an example for a custom draw functor:
* \code
* graph->setCustomDrawingFunctor(
* [](JKQTPEnhancedPainter& painter, const QRectF& bar_px, const QPointF& datapoint, Qt::Orientation orientation, JKQTPBarGraphBase* graph) {
* // draw the bar (if required), pen and brush are already set properly
* painter.drawRect(bar_px);
* // now we can add some decoration or replace the instruction above:
* // ........
* }
* );
* // enable usage of cutom draw functor
* graph->setUseCustomDrawFunctor(true);
* \endcode
*
*
* The result may look like this:
*
* \image html JKQTPBarVerticalGraphCustomDrawFunctor.png
*
* \see CustomDrawingFunctor, m_useCustomDrawFunctor, setUseCustomDrawFunctor(), \ref JKQTPlotterBarchartsCustomDrawFunctor for a detailed example
*/
CustomDrawingFunctor m_customDrawFunctor;
/** \brief enabled custom drawing by m_customDrawFunctor
*
* \see m_customDrawFunctor
*/
bool m_useCustomDrawFunctor;
/** \brief returns a FillBrushFunctor that is appropriate for the currently selected m_fillMode */ /** \brief returns a FillBrushFunctor that is appropriate for the currently selected m_fillMode */
virtual FillBrushFunctor constructFillBrushFunctor() const; virtual FillBrushFunctor constructFillBrushFunctor() const;

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB