mirror of
https://github.com/jkriege2/JKQtPlotter.git
synced 2024-11-15 10:05:47 +08:00
NEW: added example which shows how to bin a QScrollBar to a JKQTPlotter
This commit is contained in:
parent
2a23d27c60
commit
7d37140837
@ -249,6 +249,7 @@ if(JKQtPlotter_BUILD_EXAMPLES)
|
||||
paramvectorfield
|
||||
financialgraphs
|
||||
geo_bezier
|
||||
ui_bind_scrollbar
|
||||
)
|
||||
|
||||
|
||||
|
@ -207,6 +207,9 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
|
||||
<tr><td> \image html jkqtplotter_test_user_interaction_small.gif
|
||||
<td> \subpage JKQTPlotterUserInteraction
|
||||
<td> different possibilities of user-interaction in JKQtPlotter
|
||||
<tr><td> \image html ui_bind_scrollbar_small.png
|
||||
<td> \subpage JKQTPlotterUIScrollbar
|
||||
<td> using <a href="https://doc.qt.io/qt-6/qscrollbar.html">QScrollBar</a> together with JKQtPlotter
|
||||
</table>
|
||||
|
||||
|
||||
|
@ -138,7 +138,8 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
|
||||
<li>NEW: autoscaling for barcharts works now, also when stacked and unstacked charts are combined in one plot</li>
|
||||
<li>NEW: JKQTPGeoBezierCurve for drawing bezier curves of degree 1-4 (+example \ref JKQTPlotterGeometricBezier)</li>
|
||||
<li>NEW: added JKQTPCoordinateAxis::setRangeFixed() which disables changing the axis range (and thus the zoom)</li>
|
||||
<li>NEW: add JKQTPCoordinateAxis::getMin() and JKQTPCoordinateAxis::getMax() getters</li>
|
||||
<li>NEW: added JKQTPCoordinateAxis::getMin() and JKQTPCoordinateAxis::getMax() getters</li>
|
||||
<li>NEW: added example \ref JKQTPlotterUIScrollbar </li>
|
||||
</ul></li>
|
||||
|
||||
<li>JKQTMathText:<ul>
|
||||
|
@ -109,6 +109,7 @@ if (JKQtPlotter_BUILD_LIB_JKQTPLOTTER)
|
||||
add_subdirectory(symbols_and_errors)
|
||||
add_subdirectory(symbols_and_styles)
|
||||
add_subdirectory(ui)
|
||||
add_subdirectory(ui_bind_scrollbar)
|
||||
add_subdirectory(user_interaction)
|
||||
add_subdirectory(vectorfield)
|
||||
add_subdirectory(violinplot)
|
||||
|
28
examples/ui_bind_scrollbar/CMakeLists.txt
Normal file
28
examples/ui_bind_scrollbar/CMakeLists.txt
Normal file
@ -0,0 +1,28 @@
|
||||
cmake_minimum_required(VERSION 3.23)
|
||||
|
||||
set(EXAMPLE_NAME ui_bind_scrollbar)
|
||||
set(EXENAME jkqtptest_${EXAMPLE_NAME})
|
||||
|
||||
message( STATUS ".. Building Example ${EXAMPLE_NAME}" )
|
||||
|
||||
|
||||
# Set up source files
|
||||
set(SOURCES ui_bind_scrollbar.cpp )
|
||||
set(RESOURCES )
|
||||
set(UIS )
|
||||
|
||||
add_executable(${EXENAME} WIN32 ${SOURCES} ${HEADERS} ${RESOURCES} ${UIS})
|
||||
target_link_libraries(${EXENAME} JKQTPExampleToolsLib)
|
||||
target_include_directories(${EXENAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/../../lib)
|
||||
|
||||
target_link_libraries(${EXENAME} ${jkqtplotter_namespace}JKQTPlotter${jkqtplotter_LIBNAME_VERSION_PART})
|
||||
|
||||
# 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})
|
90
examples/ui_bind_scrollbar/README.md
Normal file
90
examples/ui_bind_scrollbar/README.md
Normal file
@ -0,0 +1,90 @@
|
||||
# Example (JKQTPlotter): Using a QScrollbar together with JKQtPlotter {#JKQTPlotterUIScrollbar}
|
||||
This project (see `./examples/ui_bind_scrollbar/`) shows how to use JKQTPlotter together with a <a href="https://doc.qt.io/qt-6/qscrollbar.html">QScrollBar</a> for panning.
|
||||
|
||||
The source code of the main application can be found in [`ui_bind_scrollbar.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/ui_bind_scrollbar/ui_bind_scrollbar.cpp).
|
||||
|
||||
First we create a QWidget, a plot and a QScrollBar in a layout:
|
||||
|
||||
```.cpp
|
||||
QWidget win;
|
||||
QVBoxLayout* lay=new QVBoxLayout();
|
||||
win.setLayout(lay);
|
||||
|
||||
JKQTPlotter* plot=new JKQTPlotter(&win);
|
||||
lay->addWidget(plot);
|
||||
// add a QScrollBar below the plot
|
||||
QScrollBar* scroll=new QScrollBar(Qt::Horizontal, &win);
|
||||
scroll->setMinimum(0);
|
||||
scroll->setMaximum(100);
|
||||
scroll->setPageStep(10);
|
||||
lay->addWidget(scroll);
|
||||
```
|
||||
|
||||
Then we add a plot ranging from x=0 to x=100, with 10000 datapoints:
|
||||
|
||||
```.cpp
|
||||
// 4. create a graph
|
||||
JKQTPDatastore* ds=plot->getDatastore();
|
||||
const int NPOINTS=10000;
|
||||
JKQTPXYLineGraph* graph=new JKQTPXYLineGraph(plot);
|
||||
const size_t colX=ds->addLinearColumn(NPOINTS, 0, 100, "x");
|
||||
graph->setXColumn(colX);
|
||||
graph->setYColumn(ds->addCalculatedColumnFromColumn(colX, [](double x) { return 10.0*sin(x*3.0)*fabs(cos((x/8.0))); }, "f(x)"));
|
||||
graph->setDrawLine(true);
|
||||
graph->setSymbolType(JKQTPNoSymbol);
|
||||
// ... add the graphs to the plot, so it is actually displayed
|
||||
plot->addGraph(graph);
|
||||
```
|
||||
|
||||
The plot axis range is limited to the plot range and zooming in y-direction is disabled
|
||||
|
||||
```.cpp
|
||||
plot->setAbsoluteXY(0,100,-10,10);
|
||||
// show everything in y-direction
|
||||
plot->setY(-10,10);
|
||||
// fix y-range, so no zoming occurs in y
|
||||
plot->getYAxis()->setRangeFixed(true);
|
||||
```
|
||||
|
||||
Now we need a slot for the QScrollBar (here implemented as a functor), which calculates the desired view in the graph and sets it. Note the blockSignals()-calls that stop the plot from sending signals back to the scrollbar, which would cause a strange loop due to the fact that the scrollbar only accepts integers for range and value!
|
||||
|
||||
```.cpp
|
||||
QObject::connect(scroll, &QScrollBar::valueChanged, [plot,scroll](int value) {
|
||||
const double scrollRange=scroll->maximum()-scroll->minimum()+scroll->pageStep();
|
||||
const double scrollPos=scroll->value();
|
||||
const double scrollPageSize=scroll->pageStep();
|
||||
const double scrollRelative=scrollPos/scrollRange;
|
||||
const double plotFullRange=plot->getAbsoluteXMax()-plot->getAbsoluteXMin();
|
||||
const double plotViewRange=scrollPageSize/scrollRange*plotFullRange;
|
||||
const double plotViewStart=plot->getAbsoluteXMin()+scrollRelative*plotFullRange;
|
||||
plot->blockSignals(true);
|
||||
plot->setX(plotViewStart, plotViewStart+plotViewRange);
|
||||
plot->blockSignals(false);
|
||||
});
|
||||
scroll->setValue(1); // ensure to call slot once!
|
||||
```
|
||||
|
||||
A second functor catches whenever the user zooms or pans (or otherwise changes the axis ranges) of the plot by catching the signal JKQTPlotter::zoomChangedLocally() and from that calculates the value (and pageStep) for the QScrollBar:
|
||||
|
||||
```.cpp
|
||||
QObject::connect(plot, &JKQTPlotter::zoomChangedLocally, [scroll](double newxmin, double newxmax, double newymin, double newymax, JKQTPlotter* plot) {
|
||||
const double plotFullRange=plot->getAbsoluteXMax()-plot->getAbsoluteXMin();
|
||||
const double plotViewRange=newxmax-newxmin;
|
||||
const double plotRelViewRange=(plotViewRange>=plotFullRange)?1.0:(plotViewRange/(plotFullRange-plotViewRange));
|
||||
const double plotRelViewStart=(newxmin-plot->getAbsoluteXMin())/plotFullRange;
|
||||
const double scrollRange=scroll->maximum()-scroll->minimum();
|
||||
scroll->blockSignals(true);
|
||||
scroll->setPageStep(plotRelViewRange*scrollRange);
|
||||
scroll->setValue(plotRelViewStart*scrollRange);
|
||||
scroll->blockSignals(false);
|
||||
});
|
||||
```
|
||||
|
||||
The window from this example looks like this:
|
||||
|
||||
![ui_bind_scrollbar](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/ui_bind_scrollbar.png)
|
||||
|
||||
|
||||
With the same method, it is also possible to add x- and y-scrollbars:
|
||||
|
||||
![ui_bind_scrollbar](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/ui_bind_scrollbar_win01.png)
|
198
examples/ui_bind_scrollbar/ui_bind_scrollbar.cpp
Normal file
198
examples/ui_bind_scrollbar/ui_bind_scrollbar.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
/** \example ui_bind_scrollbar.cpp
|
||||
* Use QScrollBar together with JKQtPlotter
|
||||
*
|
||||
* \ref JKQTPlotterUIScrollbar
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include <QScrollBar>
|
||||
#include <QWidget>
|
||||
#include <QBoxLayout>
|
||||
#include <QGridLayout>
|
||||
|
||||
#include "jkqtplotter/jkqtplotter.h"
|
||||
#include "jkqtplotter/graphs/jkqtplines.h"
|
||||
#include "jkqtpexampleapplication.h"
|
||||
|
||||
|
||||
void createXScrollingWindow(JKQTPExampleApplication& app, QWidget& win) {
|
||||
QVBoxLayout* lay=new QVBoxLayout();
|
||||
win.setLayout(lay);
|
||||
|
||||
JKQTPlotter* plot=new JKQTPlotter(&win);
|
||||
lay->addWidget(plot);
|
||||
// 3. add a QScrollBar below the plot
|
||||
QScrollBar* scroll=new QScrollBar(Qt::Horizontal, &win);
|
||||
scroll->setMinimum(0);
|
||||
scroll->setMaximum(100);
|
||||
scroll->setPageStep(10);
|
||||
lay->addWidget(scroll);
|
||||
|
||||
// 4. create a graph
|
||||
JKQTPDatastore* ds=plot->getDatastore();
|
||||
const int NPOINTS=10000;
|
||||
JKQTPXYLineGraph* graph=new JKQTPXYLineGraph(plot);
|
||||
const size_t colX=ds->addLinearColumn(NPOINTS, 0, 100, "x");
|
||||
graph->setXColumn(colX);
|
||||
graph->setYColumn(ds->addCalculatedColumnFromColumn(colX, [](double x) { return 10.0*sin(x*3.0)*fabs(cos((x/8.0))); }, "f(x)"));
|
||||
graph->setDrawLine(true);
|
||||
graph->setSymbolType(JKQTPNoSymbol);
|
||||
// ... add the graphs to the plot, so it is actually displayed
|
||||
plot->addGraph(graph);
|
||||
|
||||
// 5. set absolute plot range
|
||||
plot->setAbsoluteXY(0,100,-10,10);
|
||||
// show everything in y-direction
|
||||
plot->setY(-10,10);
|
||||
// fix y-range, so no zoming occurs in y
|
||||
plot->getYAxis()->setRangeFixed(true);
|
||||
|
||||
|
||||
// 6. connect scrollbar to plot
|
||||
QObject::connect(scroll, &QScrollBar::valueChanged, [plot,scroll](int value) {
|
||||
const double scrollRange=scroll->maximum()-scroll->minimum()+scroll->pageStep();
|
||||
const double scrollPos=scroll->value();
|
||||
const double scrollPageSize=scroll->pageStep();
|
||||
const double scrollRelative=scrollPos/scrollRange;
|
||||
const double plotFullRange=plot->getAbsoluteXMax()-plot->getAbsoluteXMin();
|
||||
const double plotViewRange=scrollPageSize/scrollRange*plotFullRange;
|
||||
const double plotViewStart=plot->getAbsoluteXMin()+scrollRelative*plotFullRange;
|
||||
plot->blockSignals(true);
|
||||
plot->setX(plotViewStart, plotViewStart+plotViewRange);
|
||||
plot->blockSignals(false);
|
||||
});
|
||||
scroll->setValue(1); // ensure to call slot once!
|
||||
|
||||
// 7. connect plot to QScrollBar
|
||||
QObject::connect(plot, &JKQTPlotter::zoomChangedLocally, [scroll](double newxmin, double newxmax, double newymin, double newymax, JKQTPlotter* plot) {
|
||||
const double plotFullRange=plot->getAbsoluteXMax()-plot->getAbsoluteXMin();
|
||||
const double plotViewRange=newxmax-newxmin;
|
||||
const double plotRelViewRange=(plotViewRange>=plotFullRange)?1.0:(plotViewRange/(plotFullRange-plotViewRange));
|
||||
const double plotRelViewStart=(newxmin-plot->getAbsoluteXMin())/plotFullRange;
|
||||
const double scrollRange=scroll->maximum()-scroll->minimum();
|
||||
scroll->blockSignals(true);
|
||||
scroll->setPageStep(plotRelViewRange*scrollRange);
|
||||
scroll->setValue(plotRelViewStart*scrollRange);
|
||||
scroll->blockSignals(false);
|
||||
});
|
||||
|
||||
// 8. show plotter and make it a decent size
|
||||
win.show();
|
||||
win.resize(400/plot->devicePixelRatioF(),300/plot->devicePixelRatioF());
|
||||
win.setWindowTitle("Bind JKQTPlotter to hor. QScrollBar");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void createXYScrollingWindow(JKQTPExampleApplication& app, QWidget& win) {
|
||||
QGridLayout* lay=new QGridLayout();
|
||||
win.setLayout(lay);
|
||||
|
||||
JKQTPlotter* plot=new JKQTPlotter(&win);
|
||||
lay->addWidget(plot, 0,1);
|
||||
// 3. add a QScrollBar below the plot and one on the left
|
||||
QScrollBar* scrollX=new QScrollBar(Qt::Horizontal, &win);
|
||||
scrollX->setMinimum(0);
|
||||
scrollX->setMaximum(100);
|
||||
scrollX->setPageStep(20);
|
||||
lay->addWidget(scrollX,1,1);
|
||||
QScrollBar* scrollY=new QScrollBar(Qt::Vertical, &win);
|
||||
scrollY->setMinimum(0);
|
||||
scrollY->setMaximum(100);
|
||||
scrollY->setPageStep(100);
|
||||
scrollY->setInvertedAppearance(true);
|
||||
lay->addWidget(scrollY,0,0);
|
||||
|
||||
// 4. create a graph
|
||||
JKQTPDatastore* ds=plot->getDatastore();
|
||||
const int NPOINTS=10000;
|
||||
JKQTPXYLineGraph* graph=new JKQTPXYLineGraph(plot);
|
||||
const size_t colX=ds->addLinearColumn(NPOINTS, 0, 100, "x");
|
||||
graph->setXColumn(colX);
|
||||
graph->setYColumn(ds->addCalculatedColumnFromColumn(colX, [](double x) { return 10.0*sin(x*3.0)*fabs(cos((x/8.0))); }, "f(x)"));
|
||||
graph->setDrawLine(true);
|
||||
graph->setSymbolType(JKQTPNoSymbol);
|
||||
// ... add the graphs to the plot, so it is actually displayed
|
||||
plot->addGraph(graph);
|
||||
|
||||
// 5. set absolute plot range
|
||||
plot->setAbsoluteXY(0,100,-10,10);
|
||||
plot->setXY(0,20,-10,0);
|
||||
|
||||
|
||||
// 6. connect scrollbars to plot
|
||||
QObject::connect(scrollX, &QScrollBar::valueChanged, [plot,scrollX](int value) {
|
||||
const double scrollRange=scrollX->maximum()-scrollX->minimum()+scrollX->pageStep();
|
||||
const double scrollPos=scrollX->value();
|
||||
const double scrollPageSize=scrollX->pageStep();
|
||||
const double scrollRelative=scrollPos/scrollRange;
|
||||
const double plotFullRange=plot->getAbsoluteXMax()-plot->getAbsoluteXMin();
|
||||
const double plotViewRange=scrollPageSize/scrollRange*plotFullRange;
|
||||
const double plotViewStart=plot->getAbsoluteXMin()+scrollRelative*plotFullRange;
|
||||
plot->blockSignals(true);
|
||||
plot->setX(plotViewStart, plotViewStart+plotViewRange);
|
||||
plot->blockSignals(false);
|
||||
});
|
||||
scrollX->setValue(0); // ensure to call slot once!
|
||||
QObject::connect(scrollY, &QScrollBar::valueChanged, [plot,scrollY](int value) {
|
||||
const double scrollRange=scrollY->maximum()-scrollY->minimum()+scrollY->pageStep();
|
||||
const double scrollPos=scrollY->value();
|
||||
const double scrollPageSize=scrollY->pageStep();
|
||||
const double scrollRelative=scrollPos/scrollRange;
|
||||
const double plotFullRange=plot->getAbsoluteYMax()-plot->getAbsoluteYMin();
|
||||
const double plotViewRange=scrollPageSize/scrollRange*plotFullRange;
|
||||
const double plotViewStart=plot->getAbsoluteYMin()+scrollRelative*plotFullRange;
|
||||
plot->blockSignals(true);
|
||||
plot->setY(plotViewStart, plotViewStart+plotViewRange);
|
||||
plot->blockSignals(false);
|
||||
});
|
||||
scrollY->setValue(50); // ensure to call slot once!
|
||||
|
||||
// 7. connect plot to QScrollBars
|
||||
QObject::connect(plot, &JKQTPlotter::zoomChangedLocally, [scrollX](double newxmin, double newxmax, double newymin, double newymax, JKQTPlotter* plot) {
|
||||
const double plotFullRange=plot->getAbsoluteXMax()-plot->getAbsoluteXMin();
|
||||
const double plotViewRange=newxmax-newxmin;
|
||||
const double plotRelViewRange=(plotViewRange>=plotFullRange)?1.0:(plotViewRange/(plotFullRange-plotViewRange));
|
||||
const double plotRelViewStart=(newxmin-plot->getAbsoluteXMin())/plotFullRange;
|
||||
const double scrollRange=scrollX->maximum()-scrollX->minimum();
|
||||
scrollX->blockSignals(true);
|
||||
scrollX->setPageStep(jkqtp_bounded<int>(1,plotRelViewRange*scrollRange,scrollRange));
|
||||
scrollX->setValue(jkqtp_bounded<int>(scrollX->minimum(),plotRelViewStart*scrollRange,scrollX->maximum()));
|
||||
scrollX->blockSignals(false);
|
||||
});
|
||||
QObject::connect(plot, &JKQTPlotter::zoomChangedLocally, [scrollY](double newxmin, double newxmax, double newymin, double newymax, JKQTPlotter* plot) {
|
||||
const double plotFullRange=plot->getAbsoluteYMax()-plot->getAbsoluteYMin();
|
||||
const double plotViewRange=newymax-newymin;
|
||||
const double plotRelViewRange=(plotViewRange>=plotFullRange)?1.0:(plotViewRange/(plotFullRange-plotViewRange));
|
||||
const double plotRelViewStart=(newymin-plot->getAbsoluteYMin())/plotFullRange;
|
||||
const double scrollRange=scrollY->maximum()-scrollY->minimum();
|
||||
scrollY->blockSignals(true);
|
||||
scrollY->setPageStep(jkqtp_bounded<int>(1,plotRelViewRange*scrollRange,scrollRange));
|
||||
scrollY->setValue(jkqtp_bounded<int>(scrollY->minimum(),plotRelViewStart*scrollRange,scrollY->maximum()));
|
||||
scrollY->blockSignals(false);
|
||||
});
|
||||
|
||||
// 8. show plotter and make it a decent size
|
||||
win.show();
|
||||
win.resize(400/plot->devicePixelRatioF(),300/plot->devicePixelRatioF());
|
||||
win.setWindowTitle("Bind JKQTPlotter to hor.+ver. QScrollBar");
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
JKQTPAppSettingController highDPIController(argc,argv);
|
||||
JKQTPExampleApplication app(argc, argv);
|
||||
|
||||
|
||||
// 1. create a window containing a plotter and a combobox to select the color palette
|
||||
// ... and get a pointer to the internal datastore (for convenience)
|
||||
QWidget winX, winXY;
|
||||
|
||||
createXScrollingWindow(app, winX);
|
||||
createXYScrollingWindow(app, winXY);
|
||||
|
||||
return app.exec();
|
||||
}
|
BIN
screenshots/ui_bind_scrollbar.png
Normal file
BIN
screenshots/ui_bind_scrollbar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
BIN
screenshots/ui_bind_scrollbar_small.png
Normal file
BIN
screenshots/ui_bind_scrollbar_small.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.9 KiB |
BIN
screenshots/ui_bind_scrollbar_win01.png
Normal file
BIN
screenshots/ui_bind_scrollbar_win01.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
screenshots/ui_bind_scrollbar_win01_small.png
Normal file
BIN
screenshots/ui_bind_scrollbar_win01_small.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
Loading…
Reference in New Issue
Block a user