How to transform coordinates from mousePressEvent to internal QPainter representation
I need to modify a Qt application which uses QPainter to draw a plot. What I need is to process mouse clicks on the plot and to do it, coordinates from mousePressEvent have to be converted to plotted values. Writing function which converts internal QPainter coordinates to plotted values is easy, since there is the inverse function which converts a pair of values to be plotted to internal QPainter coordinates. However, I cannot find a way to get internal QPainter coordinates from the coordinates of mousePressEvent. Is it possible?
Where are you doing your painting? QWidget? GraphicsView?
It is a QWidget subclass, the painting is done in reimplemented paintEvent (QPainter preparation) and a function called from it (plot painting itself). The code of these methods was not written by me, I have only added some plotting to the latter, using a function transforming values to be plotted to internal QPainter coordinates (also not written by me). The problem is that I cannot find any relationship between pixel coordinates relative to QWidget and internal QPainter coordinates (except that the transformation appears to be linear).
You might want to read up on the way the coordinate system transformations work "here":http://qt-project.org/doc/qt-5/coordsys.html#window-viewport-conversion
It should give you an idea on how the painter works based on logical coordinates. It should also give you an idea on how to reverse the calculations.
It seems that I have solved the problem, but I am unsure of the safety of my approach. The article on coordinate system frequently mentions QPainter::worldTransform() function, but it is not enough. Finally, I have found that the inverse transform of QTransform obtained by calling QPainter::combinedTransform() does exactly what I need.
Since the painter is only available in the paintEvent() method or functions called from it, I save the inverse transform in the last line of the paintEvent() method:
@transform = painter.combinedTransform().inverted();@
The transform variable (of QTransform type) is defined in the widget class. Then I obtain the logical coordinates by calling transform.map(event->pos()) in the mousePressEvent(QMouseEvent *event) handler. The question is: is it safe to use the transform variable outside the paintEvent()?
You are right, the approach doesn't sound very safe. Whenever the viewport changes, the transformation will change, too.
A better approach would be to research the meaning of the source coordinates of the plot. Can you create test plots and see how they behave? Where on the screen does a point with 0/0 appear? Is 100/100 visible or way off the screen? How does the plot behave when you resize the window (if that's even possible?)
The viewport of the painter is set in paintEvent() method, as everything else related to the painter. Since I save the transformation in the last line of this method, it always changes together with the viewport.
As for the source coordinates of the plot, their meaning is clear, as are the ranges of the values that can be shown. I know well where on the screen a point with given x, y values will appear. The plot also resizes automatically when window size is changed.
So it should be a matter of calculating the proper transformation yourself, so that you can convert mouse coordinates (which are always widget coordinates) to the same coordinate system the plot uses....or I did not properly understand your problem ;-)
The problem is that I do not know how to convert widget coordinates (in pixels) to logical coordinates of QPainter, or vice versa. There is no function that does one of these, except the transformation I have found.
When I wrote that I can predict the appearance of a point on the screen, I meant the following. When I try to plot (1000, 50) point, I know that it will appear in the middle of the plot (and (0, 0) will not appear at all, since it is outside the range), but I have no way to determine the pixel coordinates of the point. Moreover, it depends on the size of the plot. The only function present in the code converts the source coordinates to logical coordinates.
After experimenting with my code and reading documentation on QTransform, I am now convinced that my approach (storing inverted combined transformation matrix) is safe. It is strange, however, that such an important operation is not documented explicitly.