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:
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/ . It is from 2014, but it may put to you in the right track.
I also agree with Paolo. There’s also QCustomPlot (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).
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.
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.
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:
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.
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 . These methods only affect how selection will work.
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.
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).
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.