Are cv::viz::Widget clickable? (OpenCV C++) - c++

I've seen that there can be an event handler for mouse click in viz, but not an equivalent for the Widget.
Is there any way to use the Point returned from viz::MouseEvent() to detect a click on a widget?

No, Widgets are not clickable.
You can:
get an MouseEvent
check the click checking if type == MouseButtonPress
get the Point in window where click happened
use converTo3DRay to get a ray representing click's all depths in 3D
iterate your widgets looking for intersection. Intersection is computed differently in each king of widget.
getWidgetPose gives you the pose in reference to the camera. getWidgetPose(...).translation() gives you the place the widget is. If you aren't comfortable with this translation, you can apply converTo3DRay.
If you find many widgets, you can order by z coordinate (the lower, the closer to camera). It works for points, it's harder for other geomtry.

Related

Drag an errorbar around in a plot in qt

I am using QPainter in Qt 5.9 using C++ to make a plot and update it based on mouse events.
I would like to know how to plot an error bar that is something like this:
-
|
-
Of course the gaps shouldn't be there between the vertical and horizontal lines.
I need to be able to drag the error bar around on the plot and obtain the co-ordiantes of the center position of the error bar when the mouse button is released. So far I have made a plot with axes and labels. Not sure how to get the error bar using QPainter or any other Qt lib class.
Please provide some insight on how make/plot the error bars. Is there a simple way to do that in QPainter ?
If you are using QPainter you should implement drag-n-drop yourself. It's not that difficult if you don't have too many objects on your plot.
Here's the basic idea:
First of all render all objects. Than you need to reimplement mousePressEvent and mouseMoveEvent in your plot widget. In mousePressEvent you should check if you've clicked on the draggable object and define this object as currently being dragged. In mouseMoveEvent just move this object (if there is one) by changing its coordinates and rerender plot.
You will probably want to optimize plotting to avoid full plot rerender at each mouse move tick. This can be achieved by plotting rarely changing objects to QPixmap/QImage, than rendering this QPixmap/QImage on widget and than plotting error bars and all other kinds of objects that could change at each mouse move tick over this pixmap. At each repaint you will need to define if you need to replot just error bars (or some other dynamic objects) or all widget. I personally implement this by defining bool needFullRepaint which is set to false by widget after each render tick and is set to true after some data inside widget changed.
This is kinda low-level approach, it will require high level of skill and some time to be spend but you will be awarded with maximum control of the rendering and interactions with the widget, which is not always possible with the QGraphicsScene or QCharts
It's going to be a fairly involved project for someone who hasn't used Qt before.
You will want to use QGraphicsScene in all likelihood, rather than a QPainter example. QGraphicsScenes are way easier than QPainter for interactive examples.
Use QCharts as a starting point, they have examples for how to plot data and then move items as a result. Check out the callout example, in particular, which has you paint a callout labeling the position of the cursor on the graph.
Look at the "Drag and Drop Robot" example from Qt.
All of these are an excellent starting point for how to implement draggable features to create an interactive plot. Qt makes it easy for a generalized sense: however, for many plotting features (at least until QtCharts), Qt was much more difficult than specialized plotting libraries.

How to implement box selection in Qt?

I am trying to implement a selection box in Qt:
When the user holds down LMB and drags, a rectangle is created and drawn real time to the screen. I also want to be able to select on only one dimension.
I think overriding the methods QWidget::dragEnterEvent(QDragEnterEvent*), QWidget::dropEvent(QDropEvent*) may help, but I don't know how to dynamically obtain and draw the rect.

Qt move widget to cursor position

I am implementing a function (Using Qt) that is supposed to move a widget to the cursor position as part of a drag and drop functionality.
I have three events that get triggered, mouse down, mouse move, and mouse up. When the mouse moves and is down, a signal is sent to the widget to move itself to the cursor; however, I have encountered some strange behavior.
This simple code:
void Block::moveToCursor()
{
block->move(block->mapFromGlobal(QCursor::pos()));
qDebug() << block->mapFromGlobal(QCursor::pos());
}
where "block" is a QLabel that is a member of Block and is a child of the window's central widget.
It produces this result:
As it can be seen in the debug output, the coordinates are flip flopping (or flickering) every time there is a pixel move. The first coordinated are correct but the second set of coordinates seem to be relative to the top right corner of the window.
I have tried all the mapping functions:
block->move(block->mapFromParent(QCursor::pos()));
-Produces a similar result with the second set of coordinates relative to the center of the window.
block->move(block->mapFrom(this->block, QCursor::pos()));
-This produces an even stranger result. The block does not flicker and moves correctly with respect to the mouse, but the initial position of the block seems to be off by the distance from the top right corner of the computer screen. It also only shows one point when printed out in debug, yet it is moving on the screen. Every time you see Continue Drag, the mouse has moved at least one pixel.
Can someone explain this strange behavior to me and show me the correct way of moving the widget to the cursor at the exact position from where it was originally clicked?
To get the coordinate in relation to the parent (like wanted from move()-Method), you need to use the mapFromGlobal on the parent like this:
block->move(block->parentWidget()->mapFromGlobal(QCursor::pos()));
Just give it a try. The reason for this is, lets consider what happens when you are at position 1,1 inside the child. But the child is for example at position 123,123 from its parent top-left. You would now move it to 1,1, causing it to jump 122 pixels each.

Relative coordinates with slider widget containing thumb widget

My slider had a child button widget. I have recently changed my gui to send the mouse coordinates as relative to the widget, so if the widget is at 50,50 and the mouse is at 50,50, it will now report as 0,0.
This has created some problems for my slider. When I would drag around the button it would position to value.
The only solution I have thought of is to take the given mouse coordinate, add back the absolute position of the button, then subtract the absolute position of the slider.
I was however hoping for a solution that did not envole absolute positioning.
I used to receive the absolute mouse position, when I did, I positioned it like this:
int mousePos = getOrientation() == AGUI_HORIZONTAL ?
mouseArgs.getPosition().getX() - getAbsolutePosition().getX() :
mouseArgs.getPosition().getY() - getAbsolutePosition().getY();
setValue(positionToValue(mousePos));
mouseArgs gives the mouse position relative to the button. Not relative to the slider, which is what would be needed.
I can obtain the relative locations of the widgets, but I don't think that would do it.
Thanks
Since this is a custom GUI, I'm going to make some assumptions and restate your question to make sure I'm answering your question.
You have a slider widget that contains a thumb widget. The user can click and drag the thumb to reposition it. Your GUI sends mouse notifications to your widgets in local relative space rather than absolute screen space. Your question is how can the thumb widget respond to the mouse events to move itself around without having to use absolute coordinates?
You can do this by changing who's responsibility it is to move the thumb widget. It should be the job of the slider widget to position its thumb widget. By doing it that way, all your coordinates can be in the slider widget's local relative space. Basically it'd be something like (assuming you have some kind of event notification):
When created, the slider widget registers for the various mouse events on its child thumb widget.
When the thumb receives mouse events, it raises the event passing along its local coordinate.
Slider widget receives these events and translates the coordinate from thumb local space to slider local space (i.e., click_x = thumb_x + thumb_mouse_x).
Slider can then use this coordinate, which is in the slider's local relative space, to move the thumb.
In general, parents should be responsible for their children's layout.

Finding current mouse position in QT

This is my first attempt at writing a QT app, and I'm just trying to get a feel for how it works. My goal is to have a 400x400 widget which knows the exact position of the mouse when the mouse is hovering over it. For example, if the mouse was hovering in the top left corner, the position might be 10,10 (or something similar). If the mouse is in the bottom right corner, it might say 390,390.
Eventually, these coordinates will be displayed in a label on the main window, but that should be trivial. I'm stuck at the actual fetching of the coordinates. Any ideas?
For your widget, you must enable mouse tracking.
Then, you can either install an event filter, paying attention to mouse events and looking for the move event, or you can inherit from QWidget and override the mouse event, looking for mouse move events.
http://doc.qt.io/qt-4.8/qwidget.html#mouseTracking-prop
http://doc.qt.io/qt-4.8/eventsandfilters.html
http://doc.qt.io/qt-4.8/qmouseevent.html
If you are ever in a situation when you don't need actual tracking, just position at the moment, you can use QCursor::pos().