# Retrieving vtkChartXY data from mouse click

**URL:** https://discourse.vtk.org/t/retrieving-vtkchartxy-data-from-mouse-click/3031
**Category:** Support
**Created:** [April 12, 2020, 8:35am UTC](https://discourse.vtk.org/t/retrieving-vtkchartxy-data-from-mouse-click/3031 "2020-04-12T08:35:23Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![dwventer](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dwventer/32/1579_2.png) [@dwventer](https://discourse.vtk.org/u/dwventer)
#### Post date: [April 12, 2020, 8:35am UTC](https://discourse.vtk.org/t/retrieving-vtkchartxy-data-from-mouse-click/3031/1 "2020-04-12T08:35:23Z")

</div>

I’m trying to get the selected data point from where a user clicked on the chart with a mouse.  
I manage to get the mouse click event with the following code:

```
vtkSmartPointer <vtkCallbackCommand> callback = vtkSmartPointer <vtkCallbackCommand>::New();
callback->SetCallback(HandleChartXYMousePressEvent);
this->pvtkMFCWindowChart->GetInteractor()->AddObserver(vtkCommand::LeftButtonPressEvent, callback);

```

And then in the HandleChartXYMousePressEvent function I got the Chart object by doing this rather elaborate coding:

```
vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::SafeDownCast(obj);
int pos[2] = { 0 };
Iren->GetEventPosition(pos);
vtkRenderer* pvtkRender = iren->FindPokedRenderer(pos[0], pos[1]);
vtkPropCollection* pPropCol = pvtkRender->GetViewProps();
pPropCol->InitTraversal();
vtkContextActor* pConAct = vtkContextActor::SafeDownCast(pPropCol->GetNextProp());
vtkContextScene* pScene = pConAct->GetScene();
int nScenes = pScene->GetNumberOfItems();
vtkChartXY* pChartXY = vtkChartXY::SafeDownCast(pScene->GetItem(0));

```

(The above was simplified with removed error checking)

The problem is that I tried everything to get the data from the Chart. Can anybody point me in the right direction?

---

<div class="post-metadata">

### Author: ![Paulo\_Carvalho](https://discourse.vtk.org/user_avatar/discourse.vtk.org/paulo_carvalho/32/370_2.png) [@Paulo\_Carvalho](https://discourse.vtk.org/u/Paulo_Carvalho)
#### Post date: [April 12, 2020, 9:26pm UTC](https://discourse.vtk.org/t/retrieving-vtkchartxy-data-from-mouse-click/3031/2 "2020-04-12T21:26:50Z")

</div>

Hi, Daniel,

VTK charts are visually great, but I found that API a bit cumbersome when it comes to interactive charts. Interactive in the sense that you can pick individual curves, drag points, etc. I resorted to Qt Charts and qwt that made my life a lot easier. Anyway, after some googling I found this: [https://echnotstechno.wordpress.com/2014/08/13/interactive-2d-plots-with-vtk-the-visualization-toolkit/](https://echnotstechno.wordpress.com/2014/08/13/interactive-2d-plots-with-vtk-the-visualization-toolkit/) . It is from 2014, but it may put to you in the right track.

regards,

Paulo

---

<div class="post-metadata">

### Author: ![embeddedmz](https://discourse.vtk.org/user_avatar/discourse.vtk.org/embeddedmz/32/12_2.png) [@embeddedmz](https://discourse.vtk.org/u/embeddedmz)
#### Post date: [April 13, 2020, 11:22am UTC](https://discourse.vtk.org/t/retrieving-vtkchartxy-data-from-mouse-click/3031/3 "2020-04-13T11:22:07Z")

</div>

I also agree with Paolo. There’s also QCustomPlot ([https://www.qcustomplot.com/](https://www.qcustomplot.com/)) which is more easier to use than Qwt but it has a GPL license (it’s only an issue if you intend to use it in a commercial product). Qwt is fine, and that’s what I’m using at my current work but you will need to code Qt classes (event filters) to handle certain things more finely. Whereas, IMHO, QCP provides you with the most common features, but the quality of its code/internal degisn is lower than that of Qwt (QCP consists only of a .h and a huge cpp file).

---

<div class="post-metadata">

### Author: ![Paulo\_Carvalho](https://discourse.vtk.org/user_avatar/discourse.vtk.org/paulo_carvalho/32/370_2.png) [@Paulo\_Carvalho](https://discourse.vtk.org/u/Paulo_Carvalho)
#### Post date: [April 13, 2020, 12:35pm UTC](https://discourse.vtk.org/t/retrieving-vtkchartxy-data-from-mouse-click/3031/4 "2020-04-13T12:35:38Z")

</div>

Yes, the GPL license is an imporant detail if you opt to use Qt Charts.

---

<div class="post-metadata">

### Author: ![dwventer](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dwventer/32/1579_2.png) [@dwventer](https://discourse.vtk.org/u/dwventer)
#### Post date: [April 14, 2020, 12:15am UTC](https://discourse.vtk.org/t/retrieving-vtkchartxy-data-from-mouse-click/3031/5 "2020-04-14T00:15:58Z")

</div>

Thanks Paulo, I will need to work through the link you gave me and let you know if it solves my problem. It is definitely different that what I was expecting.

---

<div class="post-metadata">

### Author: ![Paulo\_Carvalho](https://discourse.vtk.org/user_avatar/discourse.vtk.org/paulo_carvalho/32/370_2.png) [@Paulo\_Carvalho](https://discourse.vtk.org/u/Paulo_Carvalho)
#### Post date: [April 14, 2020, 10:46am UTC](https://discourse.vtk.org/t/retrieving-vtkchartxy-data-from-mouse-click/3031/6 "2020-04-14T10:46:17Z")

</div>

Daniel,

Have you tried subclassing `vtkChartXY`? This class has mouse events such as `MouseButtonPressEvent`. I think you are better off subclassing it and overriding the mouse events instead of the hack you are doing in an external callback. Inside `vtkChartXY` events, you have seamless access to the collection of `vtkPlot`'s and, thence, to the data.

regards,

Paulo

---

<div class="post-metadata">

### Author: ![dwventer](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dwventer/32/1579_2.png) [@dwventer](https://discourse.vtk.org/u/dwventer)
#### Post date: [April 15, 2020, 1:49am UTC](https://discourse.vtk.org/t/retrieving-vtkchartxy-data-from-mouse-click/3031/7 "2020-04-15T01:49:18Z")

</div>

Paulo,

Thanks, but the `MouseButtonPressEvent` never gets called.

Regards,  
Daniel

---

<div class="post-metadata">

### Author: ![Paulo\_Carvalho](https://discourse.vtk.org/user_avatar/discourse.vtk.org/paulo_carvalho/32/370_2.png) [@Paulo\_Carvalho](https://discourse.vtk.org/u/Paulo_Carvalho)
#### Post date: [April 15, 2020, 12:08pm UTC](https://discourse.vtk.org/t/retrieving-vtkchartxy-data-from-mouse-click/3031/8 "2020-04-15T12:08:48Z")

</div>

Maybe your code needs to forward the event to the other handler codes down in the event handler chain. That can explain why `MouseButtonPressEvent` is not being called. The protocol is generally to call the superclass’ version of the event handling function like in the example below:

```cpp
void v3dMouseInteractor::OnLeftButtonDown()
{
    m_isLBdown = true;

    // Forward the event to the superclass.
    vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
}

```

If the handler expects parameters, you need to pass along what you received.

---

<div class="post-metadata">

### Author: ![dwventer](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dwventer/32/1579_2.png) [@dwventer](https://discourse.vtk.org/u/dwventer)
#### Post date: [April 16, 2020, 6:10am UTC](https://discourse.vtk.org/t/retrieving-vtkchartxy-data-from-mouse-click/3031/9 "2020-04-16T06:10:34Z")

</div>

I’m beginning to wonder if it is an issue with my setup or perhaps that I’m using `vtkMFCWindow`.

I manage to track down a message from some other VTK forum which said that they managed to get the left click events with the following code:

```
void pointSelected(vtkObject* obj, unsigned long,void*, void*)
{
    std::cout << "\nPoint selected.\n";
    // Print info of selected point
}

int main()
{
   chart->SetActionToButton(vtkChartXY::SELECT, vtkContextMouseEvent::LEFT_BUTTON);

   vtkSmartPointer<vtkCallbackCommand> keypressCallback = vtkSmartPointer<vtkCallbackCommand>::New();
   keypressCallback->SetCallback ( pointSelected );
   chart->AddObserver(vtkContextMouseEvent::LEFT_BUTTON, keypressCallback);
}

```

I tried everything but could not get it going.  
.

---

<div class="post-metadata">

### Author: ![Paulo\_Carvalho](https://discourse.vtk.org/user_avatar/discourse.vtk.org/paulo_carvalho/32/370_2.png) [@Paulo\_Carvalho](https://discourse.vtk.org/u/Paulo_Carvalho)
#### Post date: [April 16, 2020, 1:34pm UTC](https://discourse.vtk.org/t/retrieving-vtkchartxy-data-from-mouse-click/3031/10 "2020-04-16T13:34:49Z")

</div>

Hmmm… These calls are too low level (e.g. `AddObserver` is defined in `vtkObject`):

```cpp
   vtkSmartPointer<vtkCallbackCommand> keypressCallback = vtkSmartPointer<vtkCallbackCommand>::New();
   keypressCallback->SetCallback ( pointSelected );
   chart->AddObserver(vtkContextMouseEvent::LEFT_BUTTON, keypressCallback);

```

I wouldn’t use them.

Now, for your problem. First, take a look at the methods of `vtkPlot` that contains `Selection` in the name that configure how selection will work (e.g. which mouse button to use, whether it’ll be by columns or rows, etc.). There are many of them. Pick the ones that suit you: [https://vtk.org/doc/nightly/html/classvtkChart.html](https://vtk.org/doc/nightly/html/classvtkChart.html) . These methods only affect how selection will work.

Now, to the problem of getting feedback. I suggest using `vtkChart::setAnnotationLink()`. This, of course, requires creating a `vtkAnnotationLink` object: [https://vtk.org/doc/nightly/html/classvtkAnnotationLink.html](https://vtk.org/doc/nightly/html/classvtkAnnotationLink.html) . Then, I’d take a look at `vtkAnnotationLink::Set/GetCurrentSelection()`. This post may also cast light in the mechanics of how to interact with VTK charts: [http://vtk.1045678.n5.nabble.com/Selecting-Points-in-a-Plot-Rows-in-a-table-td5724213.html](http://vtk.1045678.n5.nabble.com/Selecting-Points-in-a-Plot-Rows-in-a-table-td5724213.html) .

---

<div class="post-metadata">

### Author: ![dwventer](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dwventer/32/1579_2.png) [@dwventer](https://discourse.vtk.org/u/dwventer)
#### Post date: [April 17, 2020, 5:51am UTC](https://discourse.vtk.org/t/retrieving-vtkchartxy-data-from-mouse-click/3031/11 "2020-04-17T05:51:57Z")

</div>

OK. I found part of my problem. I know why I did not get any mouse click events. I was using `vtkMFCWindow` and tried to link the `vtkContextView` with it. As far as I can tell, you are not supposed to link the context view with the MFC window (or I don’t know how to properly). I have now added my own `vtkContextActor` and from that, I retrieved the scenes needed for the `vtkChart`.

So I’m getting the mouse events now and there is actually a tooltip that was not there previously. I’m getting data point values with every second mouse click at the moment. I will try to follow your (Paulo) suggestions next week to see if I can get the datapoint with every click.

---

<div class="post-metadata">

### Author: ![Paulo\_Carvalho](https://discourse.vtk.org/user_avatar/discourse.vtk.org/paulo_carvalho/32/370_2.png) [@Paulo\_Carvalho](https://discourse.vtk.org/u/Paulo_Carvalho)
#### Post date: [April 18, 2020, 9:15pm UTC](https://discourse.vtk.org/t/retrieving-vtkchartxy-data-from-mouse-click/3031/12 "2020-04-18T21:15:36Z")

</div>

Hi, Daniel, unfortunatelly I can’t go much further since I don’t use MFC (I work with Qt). I can only assist with overall concepts of GUIs.

---

<div class="post-metadata">

### Author: ![dwventer](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dwventer/32/1579_2.png) [@dwventer](https://discourse.vtk.org/u/dwventer)
#### Post date: [April 20, 2020, 6:47am UTC](https://discourse.vtk.org/t/retrieving-vtkchartxy-data-from-mouse-click/3031/13 "2020-04-20T06:47:06Z")

</div>

No that I properly implemented the vtkChartXY it all seems easy now. Cannot believe I wasted a week on it. Anyway, for those that might have the same issue, here is some extract from my code that will show you how to get the selected data from a mouse click event:

What this does is that it will place a selection market on the mouse clicked point for demonstration purposes. So the actual selected data point is captured in the `plotPos` variable after the call to `pPlot->GetNearestPoint(position, tolerance, &plotPos)`.

The header:

```
class vtkMyChartXY :public vtkChartXY
{
public:
	vtkTypeMacro(vtkMyChartXY, vtkChartXY);
    /**
     * Creates a 2D Chart object.
     */
    static vtkMyChartXY* New();
private:
    bool MouseButtonPressEvent(const vtkContextMouseEvent& mouse) override;

    //Copied from vtkChartSelectionHelper.h
    void MakeSelection(vtkAnnotationLink* link, vtkIdTypeArray* selectionIds, vtkPlot* plot);
};

```

The cpp file:

```
vtkStandardNewMacro(vtkMyChartXY);

bool vtkMyChartXY::MouseButtonPressEvent(const vtkContextMouseEvent& mouse)
{
    size_t n = this->GetNumberOfPlots();
    vtkVector2i pos(mouse.GetScreenPos());
    if (pos[0] > this->Point1[0] && pos[0] < this->Point2[0] && pos[1] > this->Point1[1] &&
        pos[1] < this->Point2[1] && n)
    {
        //Iterate through plots
        for (size_t nPlot = 0; nPlot < n; ++nPlot) {
            vtkPlot* pPlot = this->GetPlot(nPlot);
            //Plot parent is the Plot corner (this->ChartPrivate->PlotCorners[i])
            vtkContextTransform* pPlotCorner = vtkContextTransform::SafeDownCast(pPlot->GetParent());
            if (pPlotCorner) {
                vtkVector2f plotPos, position;
                vtkTransform2D* pTransform = pPlotCorner->GetTransform();
                pTransform->InverseTransformPoints(mouse.GetPos().GetData(), position.GetData(), 1);
                // Use a tolerance of +/- 5 pixels
                vtkVector2f tolerance(std::fabs(5 * (1.0 / pTransform->GetMatrix()->GetElement(0, 0))),
                    std::fabs(5 * (1.0 / pTransform->GetMatrix()->GetElement(1, 1))));
                // Iterate through the visible plots and return on the first hit
                vtkIdType segmentIndex = -1;
                int seriesIndex = -1;
                if (pPlot && pPlot->GetVisible())
                {
                        seriesIndex = pPlot->GetNearestPoint(position, tolerance, &plotPos);
                }
                  if (seriesIndex >= 0) {
                    // Construct a new selection with the selected point in it.
                    vtkNew<vtkIdTypeArray> selectionIds;
                    
                    selectionIds->InsertNextValue(seriesIndex);
                    pPlot->SetSelection(selectionIds);
                    break; //only one selection per plot
                }
            }
        }
    }
    
	return vtkChartXY::MouseButtonPressEvent(mouse);
}

/// <summary>
/// Copies from vtkChartSelectionHelper.h
/// </summary>
void vtkMyChartXY::MakeSelection(vtkAnnotationLink* link, vtkIdTypeArray* selectionIds, vtkPlot* plot)
{
    assert(link != nullptr && selectionIds != nullptr);

    if (plot)
    {
        // We are building up plot-based selections, using multiple nodes.
        vtkSelection* selection = link->GetCurrentSelection();
        vtkSmartPointer<vtkSelectionNode> node;
        for (unsigned int i = 0; i < selection->GetNumberOfNodes(); ++i)
        {
            vtkSelectionNode* tmp = selection->GetNode(i);
            vtkPlot* selectionPlot =
                vtkPlot::SafeDownCast(tmp->GetProperties()->Get(vtkSelectionNode::PROP()));
            if (selectionPlot == plot)
            {
                node = tmp;
                break;
            }
        }
        if (!node)
        {
            node = vtkSmartPointer<vtkSelectionNode>::New();
            selection->AddNode(node.GetPointer());
            node->SetContentType(vtkSelectionNode::INDICES);
            node->SetFieldType(vtkSelectionNode::POINT);
            node->GetProperties()->Set( vtkSelectionNode::PROP(), plot);
            node->GetProperties()->Set(vtkSelectionNode::SOURCE(), plot->GetInput());
        }
        node->SetSelectionList(selectionIds);
    }
    else
    {
        // Use a simple single selection node layout, remove previous selections.
        vtkNew<vtkSelection> selection;
        vtkNew<vtkSelectionNode> node;
        selection->AddNode(node);
        node->SetContentType(vtkSelectionNode::INDICES);
        node->SetFieldType(vtkSelectionNode::POINT);
        node->SetSelectionList(selectionIds);
        link->SetCurrentSelection(selection);
    }
}

```

Hopes this helps somebody in the future.

Regards,  
Daniel

---

<div class="post-metadata">

### Author: ![Paulo\_Carvalho](https://discourse.vtk.org/user_avatar/discourse.vtk.org/paulo_carvalho/32/370_2.png) [@Paulo\_Carvalho](https://discourse.vtk.org/u/Paulo_Carvalho)
#### Post date: [April 20, 2020, 12:35pm UTC](https://discourse.vtk.org/t/retrieving-vtkchartxy-data-from-mouse-click/3031/14 "2020-04-20T12:35:57Z")

</div>

Daniel, overriding events is a quite common design in modern APIs that respond to user gestures. It’s troublesome, yes, but that’s the more design-friendly way to deal with GUI events. The others being callbacks and event filters. These may result in less coding, but they result in bad code design and, thus, prone to hideous bugs.
