JKQTPlotter: added examples for custom symbols

This commit is contained in:
jkriege2 2022-09-07 21:38:29 +02:00
parent 7846bbecf0
commit d46d82b17c
45 changed files with 483 additions and 2 deletions

View File

@ -122,6 +122,7 @@ if(JKQtPlotter_BUILD_EXAMPLES)
# the basenames are applied to the windows in the order of their windowTitle()s!
set(JKQTPlotter_GenerateDocScreenshots_From
scatter/scatter,scatter_error
scatter_customsymbol
simpletest
barchart/barchart,barchart_hor
wiggleplots/wiggleplot_x,wiggleplot_y
@ -151,6 +152,7 @@ if(JKQtPlotter_BUILD_EXAMPLES)
impulsesplot
parametriccurve/parametriccurve1,parametriccurve2
paramscatterplot
paramscatterplot_customsymbol
#paramscatterplot_image
parsedfunctionplot
rgbimageplot

View File

@ -19,6 +19,9 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
<tr><td> \image html scatter_small.png
<td> \subpage JKQTPlotterscatter
<td> `JKQTPXYScatterGraph` <br> Iterator-Interface for JKQTDatastore
<tr><td> \image html scatter_customsymbol_small.png
<td> \subpage JKQTPlotterscatterCustomSymbol
<td> `JKQTPXYScatterGraph` <br>custom symbols JKQTPCharacterSymbol, JKQTPFilledCharacterSymbol, JKQTPRegisterCustomGraphSymbol()<br> Iterator-Interface for JKQTDatastore
<tr><td> \image html speed_small.png
<td> \subpage JKQTPlotterSpeedTest
<td> `JKQTPXYLineGraph` <br> external `std::array<double,N>` data, not owned by datastore <br> live-data, measure plotting speed <br> tipps to increas plotting speed
@ -52,6 +55,9 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
<tr><td> \image html paramscatterplot_small.png
<td> \subpage JKQTPlotterParamScatter
<td> `JKQTPXYParametrizedScatterGraph` <br> C++-style QVector as plot data <br> modify scatter/points/line-graph properties by data
<tr><td> \image html paramscatterplot_customsymbol_small.png
<td> \subpage JKQTPlotterparamscatterCustomSymbol
<td> `JKQTPXYParametrizedScatterGraph` <br>custom and varying symbols using JKQTPRegisterCustomGraphSymbol()<br>iterator interface to `JKQTPDatastore`
<tr><td> \image html paramscatterplot_image_small.png
<td> \subpage JKQTPlotterParamScatterImage
<td> `JKQTPXYParametrizedScatterGraph` <br> C++-style QVector as plot data <br> rectangular arrangement of scatters <br> generative computer graphics

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -77,12 +77,14 @@ add_subdirectory(multiplot)
add_subdirectory(parametriccurve)
add_subdirectory(paramscatterplot)
add_subdirectory(paramscatterplot_image)
add_subdirectory(paramscatterplot_customsymbol)
add_subdirectory(parsedfunctionplot)
add_subdirectory(rgbimageplot)
add_subdirectory(rgbimageplot_cimg)
add_subdirectory(rgbimageplot_opencv)
add_subdirectory(rgbimageplot_qt)
add_subdirectory(scatter)
add_subdirectory(scatter_customsymbol)
add_subdirectory(speed)
add_subdirectory(stackedbars)
add_subdirectory(stepplots)

View File

@ -0,0 +1,33 @@
cmake_minimum_required(VERSION 3.16)
set(EXAMPLE_NAME paramscatterplot_customsymbol)
set(EXENAME jkqtptest_${EXAMPLE_NAME})
message( STATUS ".. Building Example ${EXAMPLE_NAME}" )
# Set up source files
set(SOURCES paramscatterplot_customsymbol.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
target_precompile_headers(${EXENAME} PRIVATE ../../lib/jkqtplotter/private/jkqtplotter_precomp.h)
# Installation
install(TARGETS ${EXENAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
#Installation of Qt DLLs on Windows
jkqtplotter_deployqt(${EXENAME})

View File

@ -0,0 +1,69 @@
# Example (JKQTPlotter): Parametrized Scatter-graph with custom symbols {#JKQTPlotterparamscatterCustomSymbol}
This project (see `./examples/paramscatterplot_customsymbol/`) demonstrates using JKQTPlotter to draw a parametrized scatter graph (JKQTPXYParametrizedScatterGraph) with custom symbols. To demonstrate this, we create a plot with several symbols, connected by a line, where each symbol shows a pie-chart with varying fractions.
The source code of the example can be found in [`paramscatterplot_customsymbol.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/paramscatterplot_customsymbol/paramscatterplot_customsymbol.cpp).
First we create a plotter window and get a pointer to the internal datastore (for convenience). Then we add three new datacolumns and obtain back inserters.
```.cpp
JKQTPlotter plot;
JKQTPDatastore* ds=plot.getDatastore();
size_t columnX=ds->addColumn("x");
auto colXInserter=ds->backInserter(columnX);
size_t columnY=ds->addColumn("y");
auto colYInserter=ds->backInserter(columnY);
size_t columnS=ds->addColumn("sym");
auto colSInserter=ds->backInserter(columnS);
```
Now we define a functor that draws a pie chart with three segments with fractions `f1` (blue), `f2` (green) and `1.0-f1-f2` (yellow):
```.cpp
auto pieFunc=[](QPainter& p, double f1, double f2) {
double f3=1.0-f1-f2;
QRectF rec(-0.5,-0.5,1,1);
p.setPen(QPen(QColor("black"), p.pen().width(), Qt::SolidLine));
p.setBrush(QBrush(QColor("blue")));
p.drawPie(rec, 90, -f1*360*16);
p.setBrush(QBrush(QColor("green")));
p.drawPie(rec, 90-f1*360*16, -f2*360*16);
p.setBrush(QBrush(QColor("yellow")));
p.drawPie(rec, 90-(f1+f2)*360*16, -f3*360*16);
};
```
Now we create data for the plot, x and y follow a simple function and the symbols are encoded in a separated column, where for each datapoint, we register a new symbol using JKQTPRegisterCustomGraphSymbol(), which is drawn by a differently parametrized (f1,f2) functor pieFunc.
```.cpp
const int Ndata=5;
for (int i=0; i<Ndata; i++) {
// put data
const double x=double(i)/double(Ndata-1);
*(colXInserter++)=x;
*(colYInserter++)=pow(x*1.3, 2.0);
*(colSInserter++)=JKQTPRegisterCustomGraphSymbol(std::bind(pieFunc, std::placeholders::_1, x*0.4, 0.5-x*0.2));
}
```
Finally we create a graph in the plot, which displays our datasets:
```.cpp
JKQTPXYParametrizedScatterGraph* graph1=new JKQTPXYParametrizedScatterGraph(&plot);
graph1->setXColumn(columnX);
graph1->setYColumn(columnY);
graph1->setSymbolSize(25);
graph1->setDrawLine(true);
graph1->setLineWidth(4);
graph1->setDrawLineInForeground(false);
graph1->setColor(QColor("black"));
graph1->setTitle(QObject::tr("pie scatter"));
```
The symbol type is stored in columnS, note however how we have to give a custom JKQTPXYParametrizedScatterGraph::symbolColumnFunctor, because the default one maps the values in the column to the range `[0...JKQTPMaxSymbolID]` in a cycling fashion (using a mod operation), but here we want to use the `stored ID directly.
```.cpp
graph1->setSymbolColumn(columnS);
graph1->setSymbolColumnFunctor(std::bind([](double /*x*/, double /*y*/, double symbolcolumn)->JKQTPGraphSymbols {
return static_cast<JKQTPGraphSymbols>(floor(symbolcolumn));
}, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
plot.addGraph(graph1);
```
The result looks like this:
![paramscatterplot_customsymbol](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/paramscatterplot_customsymbol.png)

View File

@ -0,0 +1,96 @@
/** \example scatter_customsymbol.cpp
* Usage of JKQTPScatterGraph with custom symbols
*
* \ref JKQTPlotterscatterCustomSymbol
*/
#include "jkqtpexampleapplication.h"
#include <QApplication>
#include "jkqtplotter/jkqtplotter.h"
#include "jkqtplotter/graphs/jkqtpscatter.h"
#include "jkqtpexampleapplication.h"
#include <random>
int main(int argc, char* argv[])
{
JKQTPAppSettingController highDPIController(argc,argv);
JKQTPExampleApplication app(argc, argv);
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
JKQTPlotter plot;
JKQTPDatastore* ds=plot.getDatastore();
// 2. add three columns to the JKQTPDatastore and obtain back-inserter iterators for these
size_t columnX=ds->addColumn("x");
auto colXInserter=ds->backInserter(columnX);
size_t columnY=ds->addColumn("y");
auto colYInserter=ds->backInserter(columnY);
size_t columnS=ds->addColumn("sym");
auto colSInserter=ds->backInserter(columnS);
// 3. now we define a functor that draws a pie chart with three segments with fractions
// f1 (blue), f2 (green) and 1-f1-f2 (yellow)
auto pieFunc=[](QPainter& p, double f1, double f2) {
double f3=1.0-f1-f2;
QRectF rec(-0.5,-0.5,1,1);
p.setPen(QPen(QColor("black"), p.pen().width(), Qt::SolidLine));
p.setBrush(QBrush(QColor("blue")));
p.drawPie(rec, 90, -f1*360*16);
p.setBrush(QBrush(QColor("green")));
p.drawPie(rec, 90-f1*360*16, -f2*360*16);
p.setBrush(QBrush(QColor("yellow")));
p.drawPie(rec, 90-(f1+f2)*360*16, -f3*360*16);
};
// 4. now we create data for the plot, x and y follow a simple function
// and the symbols are encoded in a separated column, where for each datapoint, we
// register a new symbol using JKQTPRegisterCustomGraphSymbol(), which is drawn by
// a differently parametrized (f1,f2) functor pieFunc.
const int Ndata=5;
for (int i=0; i<Ndata; i++) {
// put data
const double x=double(i)/double(Ndata-1);
*(colXInserter++)=x;
*(colYInserter++)=pow(x*1.3, 2.0);
*(colSInserter++)=JKQTPRegisterCustomGraphSymbol(std::bind(pieFunc, std::placeholders::_1, x*0.4, 0.5-x*0.2));
}
// 5. Finally we create a graph in the plot, which displays our datasets:
JKQTPXYParametrizedScatterGraph* graph1=new JKQTPXYParametrizedScatterGraph(&plot);
graph1->setXColumn(columnX);
graph1->setYColumn(columnY);
graph1->setSymbolSize(25);
graph1->setDrawLine(true);
graph1->setLineWidth(4);
graph1->setDrawLineInForeground(false);
graph1->setColor(QColor("black"));
graph1->setTitle(QObject::tr("pie scatter"));
// the symbol type is stored in columnS, note however how we have to give a
// custom JKQTPXYParametrizedScatterGraph::symbolColumnFunctor, because the
// default one maps the values in the column to the range [0...JKQTPMaxSymbolID]
// in a cycling fashion (using a mod operation), but here we want to use the
// stored ID directly.
graph1->setSymbolColumn(columnS);
graph1->setSymbolColumnFunctor(std::bind([](double /*x*/, double /*y*/, double symbolcolumn)->JKQTPGraphSymbols {
return static_cast<JKQTPGraphSymbols>(floor(symbolcolumn));
}, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
plot.addGraph(graph1);
// 6. autoscale the plot so the graph is contained
plot.setXY(-0.2,1.2,-0.4,2.2);
// show plotter and make it a decent size
plot.getXAxis()->setShowZeroAxis(false);
plot.getYAxis()->setShowZeroAxis(false);
plot.setGrid(false);
plot.getPlotter()->setKeyPosition(JKQTPKeyInsideTopLeft);
plot.getPlotter()->setPlotLabel(QObject::tr("Custom Parametrized Scatter Symbols Example"));
plot.show();
plot.resize(500/plot.devicePixelRatioF(),400/plot.devicePixelRatioF());
return app.exec();
}

View File

@ -0,0 +1,33 @@
cmake_minimum_required(VERSION 3.16)
set(EXAMPLE_NAME scatter_customsymbol)
set(EXENAME jkqtptest_${EXAMPLE_NAME})
message( STATUS ".. Building Example ${EXAMPLE_NAME}" )
# Set up source files
set(SOURCES scatter_customsymbol.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
target_precompile_headers(${EXENAME} PRIVATE ../../lib/jkqtplotter/private/jkqtplotter_precomp.h)
# Installation
install(TARGETS ${EXENAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
#Installation of Qt DLLs on Windows
jkqtplotter_deployqt(${EXENAME})

View File

@ -0,0 +1,113 @@
# Example (JKQTPlotter): Scatter-graph with custom symbols {#JKQTPlotterscatterCustomSymbol}
This project (see `./examples/scatter_customsymbol/`) demonstrates using JKQTPlotter to draw a scatter graph (JKQTPXYScatterGraph) with custom symbols.
The source code of the example can be found in [`jkqtplotter_scatter.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/scatter_customsymbol/scatter_customsymbol.cpp).
First we create a plotter window and get a pointer to the internal datastore (for convenience):
```.cpp
JKQTPlotter plot;
JKQTPDatastore* ds=plot.getDatastore();
```
Now we add several columns to the JKQTPDatastore and obtain back-inserter iterators for these:
```.cpp
size_t columnX=ds->addColumn("x");
auto colXInserter=ds->backInserter(columnX);
size_t columnY1=ds->addColumn("y1");
auto colY1Inserter=ds->backInserter(columnY1);
size_t columnY2=ds->addColumn("y2");
auto colY2Inserter=ds->backInserter(columnY2);
size_t columnY3=ds->addColumn("y3");
auto colY3Inserter=ds->backInserter(columnY3);
size_t columnY4=ds->addColumn("y4");
auto colY4Inserter=ds->backInserter(columnY4);
```
... and fill the columns with data
```.cpp
const int Ndata=5;
for (int i=0; i<Ndata; i++) {
// put data
const double x=double(i)/double(Ndata-1);
*(colXInserter++)=x;
*(colY1Inserter++)=3.0+pow(x*1.3, 2.0)*1.3;
*(colY2Inserter++)=2.0+pow(x*1.3, 2.0)*1.2;
*(colY3Inserter++)=1.0+pow(x*1.3, 2.0)*1.1;
*(colY4Inserter++)=pow(x*1.3, 2.0);
}
```
Now we create several graph objects of type JKQTPXYScatterGraph. Each one uses a different custom symbol style:
Graphs `graph3` and `graph4` use `JKQTPCharacterSymbol` and `JKQTPFilledCharacterSymbol` respectively to draw spades and hearts from the unicode characters `U+2660` and `U+2665` respectively. The two graphs differ in the coloring of the symbols. The `JKQTPCharacterSymbol` variant would use the color default (cycling) graph color, but here we overwrite this with `darkblue`. The `JKQTPFilledCharacterSymbol` variant uses red filled hearts with a thin black border.
```.cpp
JKQTPXYScatterGraph* graph3=new JKQTPXYScatterGraph(&plot);
graph3->setXColumn(columnX);
graph3->setYColumn(columnY3);
graph3->setSymbolType(JKQTPCharacterSymbol+QChar(0x2660).unicode());
graph3->setSymbolColor(QColor("darkblue"));
graph3->setSymbolSize(15);
graph3->setTitle(QObject::tr("spades"));
plot.addGraph(graph3);
JKQTPXYScatterGraph* graph4=new JKQTPXYScatterGraph(&plot);
graph4->setXColumn(columnX);
graph4->setYColumn(columnY4);
graph4->setSymbolType(JKQTPFilledCharacterSymbol+QChar(0x2665).unicode());
graph4->setSymbolSize(20);
graph4->setSymbolColor(QColor("black"));
graph4->setSymbolFillColor(QColor("red"));
graph4->setSymbolLineWidth(0.5);
graph4->setTitle(QObject::tr("hearts"));
plot.addGraph(graph4);
```
The more advanced graphs `graph1` and `graph2` use `JKQTPRegisterCustomGraphSymbol()` to register functors that draw user-specific symbols:
```.cpp
JKQTPCustomGraphSymbolFunctor f=[](QPainter& p) {
p.setBrush(Qt::NoBrush); // ensure that circles are not drawn filled
p.drawEllipse(QPointF(-0.33, -0.33/4.0), 0.33/2.0, 0.33/2.0);
p.drawEllipse(QPointF(0, -0.33/4.0), 0.33/2.0, 0.33/2.0);
p.drawEllipse(QPointF(0.33, -0.33/4.0), 0.33/2.0, 0.33/2.0);
p.drawEllipse(QPointF(-0.33/2.0, 0.33/4.0), 0.33/2.0, 0.33/2.0);
p.drawEllipse(QPointF(0.33/2.0, 0.33/4.0), 0.33/2.0, 0.33/2.0);
};
JKQTPGraphSymbols customsymbol_olympicrings=JKQTPRegisterCustomGraphSymbol(f);
JKQTPXYScatterGraph* graph1=new JKQTPXYScatterGraph(&plot);
graph1->setXColumn(columnX);
graph1->setYColumn(columnY1);
graph1->setSymbolType(customsymbol_olympicrings);
graph1->setSymbolSize(30);
graph1->setTitle(QObject::tr("olympics"));
plot.addGraph(graph1);
JKQTPGraphSymbols customsymbol_coloredolympicrings=JKQTPRegisterCustomGraphSymbol(
[](QPainter& p) {
p.setBrush(Qt::NoBrush); // ensure that circles are not drawn filled
const double w=p.pen().widthF();
p.setPen(QPen(QColor("red"), w));
p.drawEllipse(QPointF(-0.33, -0.33/4.0), 0.33/2.0, 0.33/2.0);
p.setPen(QPen(QColor("black"), w));
p.drawEllipse(QPointF(0, -0.33/4.0), 0.33/2.0, 0.33/2.0);
p.setPen(QPen(QColor("gold"), w));
p.drawEllipse(QPointF(0.33, -0.33/4.0), 0.33/2.0, 0.33/2.0);
p.setPen(QPen(QColor("darkgreen"), w));
p.drawEllipse(QPointF(-0.33/2.0, 0.33/4.0), 0.33/2.0, 0.33/2.0);
p.setPen(QPen(QColor("darkblue"), w));
p.drawEllipse(QPointF(0.33/2.0, 0.33/4.0), 0.33/2.0, 0.33/2.0);
});
JKQTPXYScatterGraph* graph2=new JKQTPXYScatterGraph(&plot);
graph2->setXColumn(columnX);
graph2->setYColumn(columnY2);
graph2->setSymbolType(customsymbol_coloredolympicrings);
graph2->setSymbolSize(30);
graph2->setTitle(QObject::tr("colored olympics"));
plot.addGraph(graph2);
```
Bothe variant show the olympic rings. `graph1` uses the (cycling) default graph color and `graph2` draws with user-defined colors.
The result looks like this:
![scatter_customsymbol](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/scatter_customsymbol.png)

View File

@ -0,0 +1,127 @@
/** \example scatter_customsymbol.cpp
* Usage of JKQTPScatterGraph with custom symbols
*
* \ref JKQTPlotterscatterCustomSymbol
*/
#include "jkqtpexampleapplication.h"
#include <QApplication>
#include "jkqtplotter/jkqtplotter.h"
#include "jkqtplotter/graphs/jkqtpscatter.h"
#include "jkqtpexampleapplication.h"
#include <random>
int main(int argc, char* argv[])
{
JKQTPAppSettingController highDPIController(argc,argv);
JKQTPExampleApplication app(argc, argv);
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
JKQTPlotter plot;
JKQTPDatastore* ds=plot.getDatastore();
// 2. add two columns to the JKQTPDatastore and obtain back-inserter iterators for these
size_t columnX=ds->addColumn("x");
auto colXInserter=ds->backInserter(columnX);
size_t columnY1=ds->addColumn("y1");
auto colY1Inserter=ds->backInserter(columnY1);
size_t columnY2=ds->addColumn("y2");
auto colY2Inserter=ds->backInserter(columnY2);
size_t columnY3=ds->addColumn("y3");
auto colY3Inserter=ds->backInserter(columnY3);
size_t columnY4=ds->addColumn("y4");
auto colY4Inserter=ds->backInserter(columnY4);
// 3. now we create data for a simple plot (a sine curve with random noise)
const int Ndata=5;
for (int i=0; i<Ndata; i++) {
// put data
const double x=double(i)/double(Ndata-1);
*(colXInserter++)=x;
*(colY1Inserter++)=3.0+pow(x*1.3, 2.0)*1.3;
*(colY2Inserter++)=2.0+pow(x*1.3, 2.0)*1.2;
*(colY3Inserter++)=1.0+pow(x*1.3, 2.0)*1.1;
*(colY4Inserter++)=pow(x*1.3, 2.0);
}
// 4. define custom symbol
JKQTPCustomGraphSymbolFunctor f=[](QPainter& p) {
p.setBrush(Qt::NoBrush); // ensure that circles are not drawn filled
p.drawEllipse(QPointF(-0.33, -0.33/4.0), 0.33/2.0, 0.33/2.0);
p.drawEllipse(QPointF(0, -0.33/4.0), 0.33/2.0, 0.33/2.0);
p.drawEllipse(QPointF(0.33, -0.33/4.0), 0.33/2.0, 0.33/2.0);
p.drawEllipse(QPointF(-0.33/2.0, 0.33/4.0), 0.33/2.0, 0.33/2.0);
p.drawEllipse(QPointF(0.33/2.0, 0.33/4.0), 0.33/2.0, 0.33/2.0);
};
JKQTPGraphSymbols customsymbol_olympicrings=JKQTPRegisterCustomGraphSymbol(f);
JKQTPGraphSymbols customsymbol_coloredolympicrings=JKQTPRegisterCustomGraphSymbol(
[](QPainter& p) {
p.setBrush(Qt::NoBrush); // ensure that circles are not drawn filled
const double w=p.pen().widthF();
p.setPen(QPen(QColor("red"), w));
p.drawEllipse(QPointF(-0.33, -0.33/4.0), 0.33/2.0, 0.33/2.0);
p.setPen(QPen(QColor("black"), w));
p.drawEllipse(QPointF(0, -0.33/4.0), 0.33/2.0, 0.33/2.0);
p.setPen(QPen(QColor("gold"), w));
p.drawEllipse(QPointF(0.33, -0.33/4.0), 0.33/2.0, 0.33/2.0);
p.setPen(QPen(QColor("darkgreen"), w));
p.drawEllipse(QPointF(-0.33/2.0, 0.33/4.0), 0.33/2.0, 0.33/2.0);
p.setPen(QPen(QColor("darkblue"), w));
p.drawEllipse(QPointF(0.33/2.0, 0.33/4.0), 0.33/2.0, 0.33/2.0);
});
// 4. create graphs in the plot, which plots the datasets:
JKQTPXYScatterGraph* graph1=new JKQTPXYScatterGraph(&plot);
graph1->setXColumn(columnX);
graph1->setYColumn(columnY1);
graph1->setSymbolType(customsymbol_olympicrings);
graph1->setSymbolSize(30);
graph1->setTitle(QObject::tr("olympics"));
plot.addGraph(graph1);
JKQTPXYScatterGraph* graph2=new JKQTPXYScatterGraph(&plot);
graph2->setXColumn(columnX);
graph2->setYColumn(columnY2);
graph2->setSymbolType(customsymbol_coloredolympicrings);
graph2->setSymbolSize(30);
graph2->setTitle(QObject::tr("colored olympics"));
plot.addGraph(graph2);
JKQTPXYScatterGraph* graph3=new JKQTPXYScatterGraph(&plot);
graph3->setXColumn(columnX);
graph3->setYColumn(columnY3);
graph3->setSymbolType(JKQTPCharacterSymbol+QChar(0x2660).unicode());
graph3->setSymbolColor(QColor("darkblue"));
graph3->setSymbolSize(15);
graph3->setTitle(QObject::tr("spades"));
plot.addGraph(graph3);
JKQTPXYScatterGraph* graph4=new JKQTPXYScatterGraph(&plot);
graph4->setXColumn(columnX);
graph4->setYColumn(columnY4);
graph4->setSymbolType(JKQTPFilledCharacterSymbol+QChar(0x2665).unicode());
graph4->setSymbolSize(20);
graph4->setSymbolColor(QColor("black"));
graph4->setSymbolFillColor(QColor("red"));
graph4->setSymbolLineWidth(0.5);
graph4->setTitle(QObject::tr("hearts"));
plot.addGraph(graph4);
// 6. autoscale the plot so the graph is contained
plot.setXY(-0.1,1.1,-1, 6);
// show plotter and make it a decent size
plot.getXAxis()->setShowZeroAxis(false);
plot.getYAxis()->setShowZeroAxis(false);
plot.setGrid(false);
plot.getPlotter()->setKeyPosition(JKQTPKeyInsideTopLeft);
plot.getPlotter()->setPlotLabel(QObject::tr("Custom Scatter Symbols Example"));
plot.show();
plot.resize(500/plot.devicePixelRatioF(),500/plot.devicePixelRatioF());
return app.exec();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 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: 98 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB