File: dataselection.html

package info (click to toggle)
qcustomplot 2.0.1%2Bdfsg1-4
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 8,376 kB
  • sloc: cpp: 21,746; sh: 180; makefile: 2
file content (79 lines) | stat: -rw-r--r-- 12,672 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta name="author" content="Emanuel Eichhammer" />
<meta name="copyright" content="(C) 2011-2016 Emanuel Eichhammer" />
<title>Data Selection Mechanism</title>
<link href="qcp.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top">
<a class="headerLink"  href="index.html">Main Page</a> &middot;
<a class="headerLink"  href="classoverview.html">Class Overview</a> &middot;
<a class="headerLink"  href="hierarchy.html">Hierarchy</a> &middot;
<a class="headerLink"  href="annotated.html">All Classes</a> &middot;
<a class="headerLink"  href="pages.html">Special Pages</a>
<!-- Generated by Doxygen 1.8.12 -->
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Data Selection Mechanism </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>In <a class="el" href="classQCustomPlot.html" title="The central class of the library. This is the QWidget which displays the plot and interacts with the ...">QCustomPlot</a>, each plottable can be selected by the user, or programmatically. If the user shall be able to select data in any way, the interaction flag <a class="el" href="namespaceQCP.html#a2ad6bb6281c7c2d593d4277b44c2b037a67148c8227b4155eca49135fc274c7ec">QCP::iSelectPlottables</a> must be set in <a class="el" href="classQCustomPlot.html#a5ee1e2f6ae27419deca53e75907c27e5">QCustomPlot::setInteractions</a>.</p>
<h1><a class="anchor" id="dataselection-granularity"></a>
Data selection granularity</h1>
<p>The selection granularity can be controlled via <a class="el" href="classQCPAbstractPlottable.html#ac238d6e910f976f1f30d41c2bca44ac3">QCPAbstractPlottable::setSelectable</a>, by specifying an according <a class="el" href="namespaceQCP.html#ac6cb9db26a564b27feda362a438db038">QCP::SelectionType</a>. For example, when using <a class="el" href="namespaceQCP.html#ac6cb9db26a564b27feda362a438db038a7cf82676966ebf79cc371f65278e0e16">QCP::stMultipleDataRanges</a>, the user will have full freedom over which data points he selects and which not. On the other hand if we use <a class="el" href="namespaceQCP.html#ac6cb9db26a564b27feda362a438db038aa05d2cba99c724df004d9c48971e4371">QCP::stDataRange</a>, the selection mechanism will enforce that the selected data is always one contiguous range. So if the user selects two distant data points (while holding the multi-select modifier, usually <code>Ctrl</code>), all data points in between those two points will also become selected.</p>
<p>These images show the effect of the different selection types, when the indicated selection rect was dragged:</p>
<center> <table class="doxtable">
<tr>
<td><div class="image">
<img src="selectiontype-none.png" alt="selectiontype-none.png"/>
<div class="caption">
stNone</div></div>
 </td><td><div class="image">
<img src="selectiontype-whole.png" alt="selectiontype-whole.png"/>
<div class="caption">
stWhole</div></div>
 </td><td><div class="image">
<img src="selectiontype-singledata.png" alt="selectiontype-singledata.png"/>
<div class="caption">
stSingleData</div></div>
 </td><td><div class="image">
<img src="selectiontype-datarange.png" alt="selectiontype-datarange.png"/>
<div class="caption">
stDataRange</div></div>
 </td><td><div class="image">
<img src="selectiontype-multipledataranges.png" alt="selectiontype-multipledataranges.png"/>
<div class="caption">
stMultipleDataRanges</div></div>
  </td></tr>
</table>
</center><h1><a class="anchor" id="dataselection-selectionmodes"></a>
Selection by click and selection rect</h1>
<p>The user can select data points in two ways:</p>
<p>The first method is to click on the data points with the mouse cursor. In this case, if the user wants to select multiple data points one after the other, he has to press and hold the multi-select modifier (<a class="el" href="classQCustomPlot.html#a8fc96e3b5138a06759a2a90c166df516">QCustomPlot::setMultiSelectModifier</a>), and <a class="el" href="namespaceQCP.html#a2ad6bb6281c7c2d593d4277b44c2b037aef673112c5067c3cf4cfddb62da7265d">QCP::iMultiSelect</a> must be set in <a class="el" href="classQCustomPlot.html#a5ee1e2f6ae27419deca53e75907c27e5">QCustomPlot::setInteractions</a>.</p>
<p>The other method is by dragging a selection rect over the data points that shall be selected. This is possible if <a class="el" href="classQCustomPlot.html#a810ef958ebe84db661c7288b526c0deb">QCustomPlot::setSelectionRectMode</a> is set to <a class="el" href="namespaceQCP.html#ac9aa4d6d81ac76b094f9af9ad2d3aacfa62c286e8da283a0cbb88ecac2f3f7506">QCP::srmSelect</a>. Note that while the selection rect mode is set (is not <a class="el" href="namespaceQCP.html#ac9aa4d6d81ac76b094f9af9ad2d3aacfa9032f170490d67240a6c68c2638ffab1">QCP::srmNone</a>), mouse dragging will not be forwarded to underlying layout elements. This also means that axis ranges can't be dragged with the mouse anymore. If you wish to provide your user both with axis range dragging and data selection/range zooming, use <a class="el" href="classQCustomPlot.html#a810ef958ebe84db661c7288b526c0deb">QCustomPlot::setSelectionRectMode</a> to switch between the modes just before the interaction is processed, e.g. in reaction to the <a class="el" href="classQCustomPlot.html#aca75bf9afb5dd19349c375de2a87a051">QCustomPlot::mousePress</a> or <a class="el" href="classQCustomPlot.html#a742ca4f94688bed2a685fd8a56ce5704">QCustomPlot::mouseMove</a> signals. For example you could check whether the user is holding a certain keyboard modifier, and then decide which mode shall be set.</p>
<h1><a class="anchor" id="dataselection-selectioretrieving"></a>
Retrieving the selected data</h1>
<p>Once the selection state of a plottable changes either by user interaction or programmatically, the affected plottable emits the signal <a class="el" href="classQCPAbstractPlottable.html#a3af66432b1dca93b28e00e78a8c7c1d9">QCPAbstractPlottable::selectionChanged</a>, carrying the currently selected data points in the form of a <a class="el" href="classQCPDataSelection.html">QCPDataSelection</a>. An overload of this signal is available, which just indicates in a <code>bool</code> whether the plottable has any selected data points.</p>
<p>By calling <a class="el" href="classQCustomPlot.html#a747faaab57c56891e901a1e97fa4359a">QCustomPlot::selectedPlottables</a> you can retrieve a list of plottables which currently have selected data points. The current selection of a plottable can be retrieved via <a class="el" href="classQCPAbstractPlottable.html#a040bf09f41d456284cfd39cc37aa068f">QCPAbstractPlottable::selection</a>. There is also a method dedicated to <a class="el" href="classQCPGraph.html">QCPGraph</a> plottables specifically, called <a class="el" href="classQCustomPlot.html#ad3547aded026d8a9ae6ef13a69080d06">QCustomPlot::selectedGraphs</a>.</p>
<h1><a class="anchor" id="dataselection-accessing"></a>
Accessing a data selection</h1>
<p>A <a class="el" href="classQCPDataSelection.html">QCPDataSelection</a> is a list of <a class="el" href="classQCPDataRange.html">QCPDataRange</a> instances, which themselves hold the <em>begin</em> and <em>end</em> index of the respective data range. In the case of a one-dimensional plottable (deriving from <a class="el" href="classQCPAbstractPlottable1D.html">QCPAbstractPlottable1D</a>, e.g. <a class="el" href="classQCPGraph.html">QCPGraph</a>, <a class="el" href="classQCPCurve.html">QCPCurve</a>, <a class="el" href="classQCPBars.html">QCPBars</a>, etc.) you can access the data points by index, using the data container's <a class="el" href="classQCPDataContainer.html#ae90c7457a052b223539906e6bddc0a92">at(int index)</a> method. Alternatively you can simply add the integer index to the data container's <a class="el" href="classQCPDataContainer.html#a80032518413ab8f418f7c81182fd06cb">begin()</a> iterator.</p>
<p>As an example, the following code snippet calculates the average value of a graph's data selection: </p><div class="fragment"><div class="line">  <a class="code" href="classQCPDataSelection.html">QCPDataSelection</a> selection = graph-&gt;selection();</div><div class="line">  <span class="keywordtype">double</span> sum = 0;</div><div class="line">  <span class="keywordflow">foreach</span> (<a class="code" href="classQCPDataRange.html">QCPDataRange</a> dataRange, selection.<a class="code" href="classQCPDataSelection.html#ac3b1c5e7713d380cd9e447f4556b94da">dataRanges</a>())</div><div class="line">  {</div><div class="line">    QCPGraphDataContainer::const_iterator begin = graph-&gt;data()-&gt;at(dataRange.begin()); <span class="comment">// get range begin iterator from index</span></div><div class="line">    QCPGraphDataContainer::const_iterator end = graph-&gt;data()-&gt;at(dataRange.end()); <span class="comment">// get range end iterator from index</span></div><div class="line">    <span class="keywordflow">for</span> (QCPGraphDataContainer::const_iterator it=begin; it!=end; ++it)</div><div class="line">    {</div><div class="line">      <span class="comment">// iterator &quot;it&quot; will go through all selected data points, as an example, we calculate the value average</span></div><div class="line">      sum += it-&gt;value;</div><div class="line">    }</div><div class="line">  }</div><div class="line">  <span class="keywordtype">double</span> average = sum/selection.<a class="code" href="classQCPDataSelection.html#ac9e74dd294778aa799216c3435c9c4f0">dataPointCount</a>();</div></div><!-- fragment --><p> Since <a class="el" href="classQCPDataSelection.html">QCPDataSelection</a> instances are not tightly bound to a specific plottable, it is possible that the indices they contain exceed the valid data range of a plottable. The valid data range can be retrieved by accessing the plottable's data container and calling <a class="el" href="classQCPDataContainer.html#aece90eeb2ba8d3c46d3d94023630fbc7">QCPDataContainer::dataRange</a>. With this, you can check whether a given <a class="el" href="classQCPDataSelection.html">QCPDataSelection</a> is contained in the valid range, and trim it if necessary, by using <a class="el" href="classQCPDataSelection.html#ab1ad3d5bbb55749c3f7ab1e45429c932">QCPDataSelection::contains</a>, and <a class="el" href="classQCPDataSelection.html#af5267ced53687561367105ee77b874ab">QCPDataSelection::intersection</a>, respectively.</p>
<p>Of course, the data selections returned by <a class="el" href="classQCPAbstractPlottable.html#a040bf09f41d456284cfd39cc37aa068f">QCPAbstractPlottable::selection</a> are always within the plottable's data bounds, as long as they aren't changed after retrieving the selection.</p>
<h1><a class="anchor" id="dataselection-dataatpos"></a>
Retrieving the data point at a given pixel position</h1>
<p>If you only want to find out which data point of a plottable is at or close to a given pixel position (without the need for a click or actual selection event), you can use <a class="el" href="classQCPAbstractPlottable.html#a38efe9641d972992a3d44204bc80ec1d">QCPAbstractPlottable::selectTest</a>. For example, the following code retrieves an iterator to the data point closest to a given QPoint in pixel coordinates:</p>
<div class="fragment"><div class="line">  QCPGraphDataContainer::const_iterator it = graph-&gt;data()-&gt;constEnd();</div><div class="line">  QVariant details;</div><div class="line">  <span class="keywordflow">if</span> (graph-&gt;selectTest(QPoint(123, 456), <span class="keyword">false</span>, &amp;details)) <span class="comment">// QPoint could be e.g. event-&gt;pos() of a mouse event</span></div><div class="line">  {</div><div class="line">    <a class="code" href="classQCPDataSelection.html">QCPDataSelection</a> dataPoints = details.value&lt;<a class="code" href="classQCPDataSelection.html">QCPDataSelection</a>&gt;();</div><div class="line">    <span class="keywordflow">if</span> (dataPoints.<a class="code" href="classQCPDataSelection.html#ac9e74dd294778aa799216c3435c9c4f0">dataPointCount</a>() &gt; 0)</div><div class="line">      it = graph-&gt;data()-&gt;at(dataPoints.<a class="code" href="classQCPDataSelection.html#a6956acf6a9a49a353b4f9b58608978ad">dataRange</a>().begin());</div><div class="line">  }</div><div class="line">  <span class="comment">// iterator &quot;it&quot; now carries the data point at pixel coordinates (123, 456), or constEnd if no data point was hit.</span></div></div><!-- fragment --><p> <br />
<br />
<br />
 <br />
<br />
<br />
 </p>
</div></div><!-- contents -->
</body>
</html>