How to know if the mouse hovers over a widget in QT? - c++

I am trying to implement in my program, that if the mouse hovers over my QChartView widget, that I get back the coordinates of the cursor.
I already tried, by installing an event filter on the widget
ui->chartView->setMouseTracking(true);
ui->chartView->installEventFilter(this);
and then writing the method for a mouse event
void MainWindow::mouseMoveEvent(QMouseEvent* event) {
qDebug() << event->pos();
}
but, i only get output when I click on the Mainwindow and hold the mousebutton which I clicked. When I click on the widget chartView I dont get any output.
I need to get output, when the mouse is hovering over the chartview

You don't need an event filter. You need to reimplement the methods QWidget::enterEvent() and QWidget::leaveEvent().
enterEvent() is called when the mouse enters the widget and leaveEvent() when it leaves it again.

Related

How to enable mouse tracking on a QWindow

I'm using a QWindow (Not a QMainWindow) with OpenGL. I need to use a QWindow to correctly control the OGL context.
I'm trying to follow the Scribble example to implement something similar to panning, but I can't find a paradigmatic way to trigger the mouseMoveEvent().
How can I get a "tooltip" effect where mouseMoveEvent() is constantly triggered, similar to setMouseTracking()?
It works fine for me. I created a test program with a MainWindow that inherits QWindow instead of QMainWindow, and handles the mouse move event to print the cursor position:
void MainWindow::mouseMoveEvent(QMouseEvent *e)
{
qDebug("%d, %d", e->pos().x(), e->pos().y());
}
It works, as I move the mouse I get events even without pressing any mouse buttons.
If mouse tracking is disabled (the default), the widget only receives mouse move events when at least one mouse button is pressed while the mouse is being moved.
you can call hasMouseTracking() or setMouseTracking() to control mouse's tracing state.
When mouse is traced, mouseMoveEvent() will be called, and you can reimpletment mouseMoveEven() to acquire mouse position, just as #sashoalm did.
BTW, mouse event is always transfered to your app, but filtered by it's parent or itself. You can reimpletment eventFilter() to code your own filter.

I want to show menu when cursor hovers over pushbutton and close menu when cursor is moved away

I am using Qt on Ubuntu.
I have a menu on QPushButton. I want to show menu when cursor hovers over the QPushButton and close menu when cursor is moved away.
Showing a popup menu on "hover" event seems to violate the user experience, as users expect to see the popup when they click the button. This is called a menu button. If you really want to use hover event, you may subclass the QPushButton class and use its respective events. However if you would like to use a menu button, you can try this:
QMenu *menu = new QMenu();
QAction *testAction = new QAction("test menu item", this);
menu->addAction(testAction);
button->setMenu(menu);
Documentation on QPushButton::setMenu.
You have to implement your owen QPushButton. Let's start by checking the MouseMoveEvent to handle when the mouse hover the widget.
To check if the cursos pos is inside your widget:
void CustomPushButton::mousePressEvent(QMouseEvent *e) {
const QRect widgetRect = ui->followersWidget->geometry();
const QPoint mousePos = ui->followersWidget->mapFromGlobal(QCursor::pos()); // or e->pos()
if (widgetRect.contains(mousePos)) {
// Mouse inside the widget, lets show the menu
} else {
// Mouse outside the widget, if the menu is open, close it.
}
QWidget::mousePressEvent(e);
}
To show/hide the menu you could use the QMenu::popup(..), from Qt Doc:
Displays the menu so that the action atAction will be at the specified global position p. To translate a widget's local coordinates into global coordinates, use QWidget::mapToGlobal().

Custom Qt QGraphicsItem tooltip

I'm looking for some ways to implement a simple custom tooltip for QGraphicsItem.
I know that I can use setToolTip to set text for tooltip. Now what I want is to change the text dynamically when the mouse hovers at different parts of a QGraphicsItem object.
What I'm thinking to do is when I get an event QEvent::ToolTip, I change the tooltip text in that event handler. However, I cannot find an event function that recieve QEvent::ToolTip for QGraphicsItem.
Or is there some ways to handle an event that mouse hovers for 2 seconds.
How can I make it?
You could implement the hoverMoveEvent in your derived QGraphicsItem class, and set the tooltip based on the position within the graphics item
void MyItem::hoverMoveEvent(QGraphicsSceneHoverEvent* event)
{
QPointF p = event->pos();
// use p.x() and p.y() to set the tooltip accrdingly, for example:
if (p.y() < height()/2)
setTooltip("Upper Half");
else
setTooltip("Bottom Half");
}
Notice that you have to enable hover events for your item.

Confused by doubleclickevent and mousepressevent in Qt

The situation is:
In side a QGraphicsView, I used its doubleClickEvent function to create a QGraphicsItem.
I rewrite the QGraphicsItem's mousePressEvent function to simply print a qDebug information.
However, what I found is that: even if I just double click to create that QGraphicsItem, the newly created QGraphicsItem's mousePressEvent is also called.
How would this happen? What can I do to prevent this?
A QGraphicsView is a widget, so it has a doubleClickEvent. In contrast, a QGraphicsItem is not a widget, but has a mousePressEvent.
When you override events, if you don't want them to be propagated to other objects, you need to accept the event to tell the system that you've handled it.
void MyGraphicsView::mouseDoubleClickEvent(QMouseEvent * event)
{
// Create a graphics item..
...
event->accept(); // tell the system that the event has been handled
}
Without accepting the event, the double click is passed on to the QGraphicsScene and then QGraphicsItem.
If you want to be able to double-click to create an item when clicking on an empty area of a scene, but have an item react if you double-click on an item, you can override the scene's mouseDoubleClickEvent instead of the view and check if there's an item at the cursor position before deciding upon whether or not to create an item, or pass the event on.
void QGraphicsScene::mouseDoubleClickEvent( QGraphicsSceneMouseEvent * mouseEvent )
{
if(items(mouseEvent->scenePos()).isEmpty()) // if no items are at this position
{
// create new graphics item
...
mouseEvent->accept(); // don't propagate the event
}
// no items, so allow the event to propagate by doing nothing
}

How to keep a QSlider activated to allow movements with arrows at any time

I would like to be able to move a QSlider with arrows of the keyboard at any time.
I want to be able to click anywhere on the QWindow and keep QSlider activated to move the cursor with the arrows.
My problem is that move the cursor with arrows is only allowed if we click on the QSlider before.
I hope my question is clear enough.
Does anyone know how to move the QSlider with arrows of the keyboard without clicking on the QSlider before please?
There are two approaches:
In Qt terms, you'd like to give slider the focus. Widgets have the setFocus method, so you need to call slider->setFocus(Qt::OtherFocusReason).
Since you want the slider to get focus whenever the underlying window has focus, you need to put the setFocus call in your implementation of focusInEvent for the parent widget.
You can forward the key events from the underlying widget to the slider. In the parent widget, reimplement keyPressEvent and keyReleaseEvent. When the desired keys are detected, forward them to the slider:
// same for keyReleaseEvent!
void MyWindow::keyPressEvent(QKeyEvent * ev) {
if (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) {
slider->event(ev);
}
}