mirror of
https://github.com/jkriege2/JKQtPlotter.git
synced 2024-12-25 10:01:38 +08:00
a67975e680
- some reorganizations into different files - additional options for graph filling (color gradients, textures, ...) as provided by QBrush - PREPARATIONS: added a general feature to JKQTPPlotElement which allows to show a graph in a highlighted state (if supported by the derived graph class!) - JKQTPXYParametrizedScatterGraph: added functors to transform column values into symbol type+size and line-width to give even more control - JKQTPStepHorizontalGraph has been renamed to JKQTPSpecialLineHorizontalGraph (vertical variants also) and have gained additional features (baseline for filling and drawing of symbols) - filled curve graphs (e.g. JKQTPSpecialLineHorizontalGraph) are now merely a specializedly initialized JKQTPSpecialLineHorizontalGraph
284 lines
11 KiB
C++
284 lines
11 KiB
C++
#include "test_styling.h"
|
|
#include "ui_test_styling.h"
|
|
#include "jkqtplotter/jkqtplotter.h"
|
|
#include "jkqtplotter/jkqtpgraphsscatter.h"
|
|
#include "jkqtplotter/jkqtpgraphsbarchart.h"
|
|
#include "jkqtplotter/jkqtpgraphsimage.h"
|
|
#include "jkqtplotter/jkqtpgraphsgeometric.h"
|
|
#include <QDir>
|
|
#include <QTextStream>
|
|
#include <QFileDialog>
|
|
|
|
TestStyling::TestStyling(QWidget *parent) :
|
|
QMainWindow(parent),
|
|
ui(new Ui::TestStyling)
|
|
{
|
|
// set up the GUI
|
|
ui->setupUi(this);
|
|
ui->splitter->setStretchFactor(0,1);
|
|
ui->splitter->setStretchFactor(1,1);
|
|
|
|
// initialize a simple plot
|
|
initPlot();
|
|
|
|
// connect GUI to JKQTPlotter
|
|
connect(ui->chkGrid, SIGNAL(toggled(bool)), ui->plot, SLOT(setGrid(bool)));
|
|
connect(ui->chkLogX, SIGNAL(toggled(bool)), ui->plot->getXAxis(), SLOT(setLogAxis(bool)));
|
|
connect(ui->chkLogY, SIGNAL(toggled(bool)), ui->plot->getYAxis(), SLOT(setLogAxis(bool)));
|
|
connect(ui->chkDebugBoxes, SIGNAL(toggled(bool)), ui->plot->getPlotter(), SLOT(enableDebugShowRegionBoxes(bool)));
|
|
|
|
// store JKQTPlotter plotterStyle to a temporary INI-file
|
|
// and then load that temporary file into the plainTextEdit,
|
|
// using on_btnLoad_clicked(tmpfn). This ensures that the currently
|
|
// set plotterStyle is visible in the plainTextEdit and can be edited
|
|
// by the user
|
|
QString tmpfn=QDir::tempPath()+"/jkqtplotter_config.tmp";
|
|
{
|
|
QSettings settings(tmpfn, QSettings::IniFormat);
|
|
ui->plot->saveCurrentPlotterStyle(settings);
|
|
}
|
|
on_btnLoad_clicked(tmpfn);
|
|
QFile::remove(tmpfn);
|
|
}
|
|
|
|
TestStyling::~TestStyling()
|
|
{
|
|
delete ui;
|
|
if (!plotExtra.isNull()) {
|
|
plotExtra->close();
|
|
plotExtra.clear();
|
|
}
|
|
}
|
|
|
|
void TestStyling::on_btnUpdate_clicked()
|
|
{
|
|
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
|
// In this function, we store the data from the plainTextEdit into a temporary file
|
|
// tmpfn and the use that file's contents to create a QSettings object, which is used
|
|
// to read the plotterStyle into the JKQTPlotter-object ui->plot (using loadCurrentPlotterStyle(settings) )
|
|
QString tmpfn=QDir::tempPath()+"/jkqtplotter_config.tmp";
|
|
{
|
|
QFile data(tmpfn);
|
|
if (data.open(QFile::WriteOnly|QFile::Text)) {
|
|
QTextStream out(&data);
|
|
out << ui->plainTextEdit->toPlainText();
|
|
}
|
|
}
|
|
{
|
|
QSettings settings(tmpfn, QSettings::IniFormat);
|
|
ui->plot->loadCurrentPlotterStyle(settings);
|
|
initPlot();
|
|
ui->chkDebugBoxes->setChecked(ui->plot->getPlotter()->isDebugShowRegionBoxesEnabled());
|
|
}
|
|
QFile::remove(tmpfn);
|
|
QApplication::restoreOverrideCursor();
|
|
}
|
|
|
|
void TestStyling::on_btnLoad_clicked(const QString& filename)
|
|
{
|
|
// loads a plotterTsyle INI file from harddisk into the plainTextEdit
|
|
// and then calls on_btnUpdate_clicked() to apply it immediately to plot
|
|
QString fn=filename;
|
|
if (fn.size()==0) {
|
|
fn=QFileDialog::getOpenFileName(this, tr("Open Styling INI-File"),
|
|
"",
|
|
tr("Styling INI (*.ini *.cfg *.txt)"));
|
|
}
|
|
if (fn.size()>0) {
|
|
QFile data(fn);
|
|
if (data.open(QFile::ReadOnly|QFile::Text)) {
|
|
ui->plainTextEdit->setPlainText(data.readAll());
|
|
}
|
|
}
|
|
on_btnUpdate_clicked();
|
|
}
|
|
|
|
void TestStyling::on_btnSave_clicked()
|
|
{
|
|
// stores the contents of plainTextEdit into a file on the harddisk
|
|
QString fn=QFileDialog::getSaveFileName(this, tr("Save Styling INI-File"),
|
|
"",
|
|
tr("Styling INI (*.ini *.cfg *.txt)"));
|
|
if (fn.size()>0) {
|
|
QFile data(fn);
|
|
if (data.open(QFile::WriteOnly|QFile::Text)) {
|
|
QTextStream out(&data);
|
|
out << ui->plainTextEdit->toPlainText();
|
|
}
|
|
QPixmap img=ui->plot->grab();
|
|
img.save(fn+".png", "png");
|
|
ui->plot->saveImage(fn+".export.png", false);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void TestStyling::initPlot()
|
|
{
|
|
|
|
ui->plot->setPlotUpdateEnabled(false);
|
|
|
|
// 0. get a pointer to the internal datastore (for convenience)
|
|
JKQTPDatastore* ds=ui->plot->getDatastore();
|
|
|
|
// 1. clear old graphs/data
|
|
ui->plot->clearGraphs(true);
|
|
ds->clear();
|
|
|
|
// 2. now we create data for a simple plot (a sine curve)
|
|
QVector<double> X, Y1, Y2, img, X3, Y3, Y3err, Xbar, Ybar, Ybar2;
|
|
const int Ndata=100;
|
|
for (int i=0; i<Ndata; i++) {
|
|
const double x=double(i)/double(Ndata)*8.0*M_PI;
|
|
X<<x;
|
|
Y1<<1.1+sin(x);
|
|
Y2<<1.1+sin(x)*exp(-0.2*x);
|
|
if (i%5==0) {
|
|
X3<<x;
|
|
Y3<<(1.5+Y1.last());
|
|
Y3err<<(double(i+5)/double(Ndata)*0.5);
|
|
}
|
|
if (i>0 && i%20==0) {
|
|
Xbar<<x;
|
|
Ybar<<(double(i+5)/double(Ndata)*(-1.5));
|
|
Ybar2<<(double(i+5)/double(Ndata)*(-1.2));
|
|
}
|
|
}
|
|
auto fgauss=[](double x, double y, double x0, double y0, double sx, double sy) {
|
|
return exp(-2.0*(x-x0)*(x-x0)/sx/sx-2.0*(y-y0)*(y-y0)/sy/sy);
|
|
};
|
|
for (int i=0; i<Ndata; i++) {
|
|
for (int j=0; j<Ndata; j++) {
|
|
img.push_back(fgauss(j,i,Ndata/3,Ndata/3,Ndata/5,Ndata/3)+fgauss(j,i,Ndata*3/4,Ndata*2/3,Ndata/2,Ndata/4));
|
|
}
|
|
}
|
|
|
|
// 3. make data available to JKQTPlotter by adding it to the internal datastore.
|
|
// Note: In this step the data is copied (of not specified otherwise), so you can
|
|
// reuse X and Y afterwards!
|
|
// the variables columnX and columnY will contain the internal column ID of the newly
|
|
// created columns with names "x" and "y" and the (copied) data from X and Y.
|
|
size_t columnX=ds->addCopiedColumn(X, "x");
|
|
size_t columnY1=ds->addCopiedColumn(Y1, "y1");
|
|
size_t columnY2=ds->addCopiedColumn(Y2, "y2");
|
|
size_t columnImg=ds->addCopiedColumn(img, "img");
|
|
size_t columnX3=ds->addCopiedColumn(X3, "x3");
|
|
size_t columnY3=ds->addCopiedColumn(Y3, "y3");
|
|
size_t columnY3err=ds->addCopiedColumn(Y3err, "y3err");
|
|
size_t columnXbar=ds->addCopiedColumn(Xbar, "xbar");
|
|
size_t columnYbar=ds->addCopiedColumn(Ybar, "ybar");
|
|
size_t columnYbar2=ds->addCopiedColumn(Ybar2, "Ybar2");
|
|
|
|
// 4. create a graph in the plot, which plots the dataset X/Y:
|
|
JKQTPColumnMathImage* graphI=new JKQTPColumnMathImage(ui->plot);
|
|
graphI->setImageColumn(columnImg);
|
|
graphI->setNx(Ndata);
|
|
graphI->setNy(Ndata);
|
|
graphI->setColorBarTopVisible(true);
|
|
graphI->setColorBarRightVisible(true);
|
|
graphI->setX(0.5);
|
|
graphI->setY(-1.5);
|
|
graphI->setWidth(5);
|
|
graphI->setHeight(1);
|
|
graphI->setTitle(QObject::tr("2{\\times}Gauss"));
|
|
ui->plot->addGraph(graphI);
|
|
|
|
JKQTPXYLineGraph* graph1=new JKQTPXYLineGraph(ui->plot);
|
|
graph1->setXColumn(columnX);
|
|
graph1->setYColumn(columnY1);
|
|
graph1->setTitle(QObject::tr("sine graph $f(x)=\\sin(x)$"));
|
|
ui->plot->addGraph(graph1);
|
|
|
|
JKQTPXYLineGraph* graph2=new JKQTPXYLineGraph(ui->plot);
|
|
graph2->setXColumn(columnX);
|
|
graph2->setYColumn(columnY2);
|
|
graph2->setSymbolType(JKQTPNoSymbol);
|
|
//graph2->setTitle(QObject::tr("sine{\\cdot}exp graph $f(x)=\\sin(x)\\cdot\\exp\\left(-\\frac{x}{5}\\right)$"));
|
|
graph2->setTitle(QObject::tr("sine*exp graph"));
|
|
ui->plot->addGraph(graph2);
|
|
|
|
JKQTPXYLineErrorGraph* graph3=new JKQTPXYLineErrorGraph(ui->plot);
|
|
graph3->setXColumn(columnX3);
|
|
graph3->setYColumn(columnY3);
|
|
graph3->setYErrorColumn(columnY3err);
|
|
graph3->setDrawLine(false);
|
|
graph3->setTitle(QObject::tr("sine \\pm errors graph"));
|
|
ui->plot->addGraph(graph3);
|
|
|
|
JKQTPBarVerticalGraph* graphb=new JKQTPBarVerticalGraph(ui->plot);
|
|
graphb->setXColumn(columnXbar);
|
|
graphb->setYColumn(columnYbar);
|
|
graphb->setTitle(QObject::tr("barchart"));
|
|
ui->plot->addGraph(graphb);
|
|
|
|
JKQTPBarVerticalGraph* graphb2=new JKQTPBarVerticalGraph(ui->plot);
|
|
graphb2->setXColumn(columnXbar);
|
|
graphb2->setYColumn(columnYbar2);
|
|
graphb2->setTitle(QObject::tr("2^{nd} barchart"));
|
|
ui->plot->addGraph(graphb2);
|
|
graphb2->autoscaleBarWidthAndShiftSeparatedGroups();
|
|
|
|
|
|
// 6. autoscale the plot so the graph is contained
|
|
ui->plot->zoomToFit();
|
|
|
|
ui->plot->getPlotter()->setPlotLabel("Sine Plots - User-Interaction Example");
|
|
ui->plot->getXAxis()->setAxisLabel("x-axis");
|
|
ui->plot->getYAxis()->setAxisLabel("y-axis");
|
|
|
|
ui->plot->setPlotUpdateEnabled(true);
|
|
ui->plot->redrawPlot();
|
|
|
|
if (!plotExtra) {
|
|
plotExtra=new JKQTPlotter;
|
|
plotExtra->show();
|
|
plotExtra->resize(width(),300);
|
|
plotExtra->move(pos().x(), pos().y()+height()+32);
|
|
}
|
|
plotExtra->setPlotUpdateEnabled(false);
|
|
plotExtra->clearGraphs(true);
|
|
plotExtra->getPlotter()->setBackgroundColor(ui->plot->getPlotter()->getBackgroundColor());
|
|
plotExtra->getPlotter()->setExportBackgroundColor(ui->plot->getPlotter()->getExportBackgroundColor());
|
|
plotExtra->getPlotter()->setPlotBackgroundColor(ui->plot->getPlotter()->getPlotBackgroundColor());
|
|
plotExtra->getXAxis()->setDrawMode1(JKQTPCADMnone);
|
|
plotExtra->getXAxis()->setDrawMode2(JKQTPCADMnone);
|
|
plotExtra->getYAxis()->setDrawMode1(JKQTPCADMnone);
|
|
plotExtra->getYAxis()->setDrawMode2(JKQTPCADMnone);
|
|
double x=1;
|
|
double xlineend=6;
|
|
double y=1;
|
|
double xmax=15;
|
|
int cnt=0;
|
|
for (auto s: ui->plot->getPlotter()->getCurrentPlotterStyle().defaultGraphSymbols) {
|
|
plotExtra->addGraph(new JKQTPGeoSymbol(plotExtra.data(), x, y, s, 12, QColor("red"), QColor("salmon") ));
|
|
x+=1;
|
|
xmax=qMax(x, xmax);
|
|
if (cnt>0 && cnt%25==0) {
|
|
x=1;
|
|
y+=1.0;
|
|
}
|
|
cnt++;
|
|
}
|
|
y=y+1;
|
|
double ycoltest=y;
|
|
for (auto s: ui->plot->getPlotter()->getCurrentPlotterStyle().defaultGraphPenStyles) {
|
|
plotExtra->addGraph(new JKQTPGeoLine(plotExtra.data(), 1,y,xlineend,y,QColor("red"), 2, s));
|
|
plotExtra->addGraph(new JKQTPGeoLine(plotExtra.data(), 1,y-0.25,xlineend,y-0.25,QColor("maroon"), 1, s));
|
|
y+=0.75;
|
|
}
|
|
x=xlineend+1;
|
|
double dx=(xmax-xlineend-1.0)/static_cast<double>(ui->plot->getPlotter()->getCurrentPlotterStyle().defaultGraphColors.size());
|
|
for (auto s: ui->plot->getPlotter()->getCurrentPlotterStyle().defaultGraphColors) {
|
|
plotExtra->addGraph(new JKQTPGeoLine(plotExtra.data(), x,ycoltest,x,y-0.5,s,5));
|
|
plotExtra->addGraph(new JKQTPGeoRectangle(plotExtra.data(), x+dx/2,(ycoltest+y-0.5)/2.0, dx*0.5, y-ycoltest-0.5, s,1, Qt::SolidLine, JKQTPGetDerivedColor(ui->plot->getPlotter()->getCurrentPlotterStyle().graphFillColorDerivationMode, s)));
|
|
x+=dx;
|
|
}
|
|
plotExtra->zoomToFit();
|
|
plotExtra->setX(0, plotExtra->getXMax()+2);
|
|
plotExtra->setY(0, plotExtra->getYMax()+1);
|
|
plotExtra->setGrid(false);
|
|
plotExtra->getPlotter()->setPlotLabel("default symbols/lines/colors");
|
|
plotExtra->setPlotUpdateEnabled(true);
|
|
plotExtra->redrawPlot();
|
|
}
|