How to detect a mouse click inside a tooltip in Qt? - qt

I have a Qt application in which certain QLabel's display a tooltip if a certain internal condition occurs.
Since the tooltip has a timeout and is hidden by Qt automatically, the tooltip is kept alive by the application by showing the tooltip every 3 seconds (I did not find any mechanism to tell Qt to show a tooltip indefinitely).
The tooltip is displayed until the user clicks on the QLabel itself: the tooltip is not refreshed any more and disappears.
I now have a new requirement that the tooltip should also disappear if the user clicks on the tooltip itself. Is there a signal that is sent when the user clicks on a visible tooltip? Or is it necessary to use some more sophisticated technique?
EDIT
I have checked my code again, here is some extra information.
Qt does detect a mouse click on a tooltip and hides it, but the application immediately shows the tooltip again.
What I would like to do is that Qt informs my code of the mouse-clicked event, so that it stops showing the tooltip again and again. I have two possible solutions in mind, but I do not know if either of them is technically feasible:
Remove tooltip timeout: when a tooltip is shown, it remains visible as long as the user does not click on it. How can I display a tooltip without a timeout in Qt?
Keep the tooltip visible by repeatedly showing it; detect a mouse clicked on the tooltip in order to stop the keep-alive loop. How do I receive a signal when the user clicks on a tooltip?

Under the hood, the actual class that implements the tooltip is a private QLabel-derived class called QTipLabel:
http://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/kernel/qtooltip.cpp#line119
There's nothing published in the interface to get at an instance of that class from QToolTip, so intercepting clicks would only be done with some sort of ill-advised hack.
That said: among the events that should "hideTipImmediately" is QEvent::mouseButtonPress...in fact, there's an event filter installed so that any click in the app will hide it:
http://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/kernel/qtooltip.cpp#line325
So if you're not seeing the tooltip disappear when it's being clicked on, there's a bug. (Clicking on tooltips hides them for me in Qt-based apps under Kubuntu.)

Note the definition of QToolTip::showText:
void QToolTip::showText ( const QPoint & pos, const QString & text,
QWidget * w, const QRect & rect ) [static] Shows text as a tool tip,
with the global position pos as the point of interest. The tool tip
will be shown with a platform specific offset from this point of
interest.
If you specify a non-empty rect the tip will be hidden as soon as you
move your cursor out of this area.
The rect is in the coordinates of the widget you specify with w. If
the rect is not empty you must specify a widget. Otherwise this
argument can be 0 but it is used to determine the appropriate screen
on multi-head systems.
If text is empty the tool tip is hidden. If the text is the same as
the currently shown tooltip, the tip will not move. You can force
moving by first hiding the tip with an empty text, and then showing
the new tip at the new position.
Thus, you can supply the rectangle in which the QToolTip is to be presented. Then, if what you want to do is close the QToolTip only when the user clicks on it, you can capture mouseButtonPress events as #HostileFork pointed out and then close the tooltip only when the coordinates of the event fall within it.

Related

Is there a way to show tooltip on disabled QWidget

I have a Qt form, where I have a button and menu. For various reasons I can disable certain elements, e.g button or some actions in the menu.
Is there a way I could show a tooltip or when the mouse is hovered over the disabled button or menu item with an explanation as to why it is disabled?
I am using Qt 4.8.
Thanks!
You can set the tooltip dynamically based on the state of the QWidget or by simply toggling both at the same time. Upon disabling/enabling the widget from somewhere just call QWidget::setToolTip(...) with the QString you want the tooltip to display when hovering with the mouse over the given widget. For example if you have a public slot called toggleButton(bool toggleFlag) which toggles the enable-setting of a button you can do:
void MyWidget::toggleButton(bool toggleFlag) {
this->ui->myButton->setEnabled(toggleFlag);
this->ui->myButton->setToolTip(toggleFlag ? QString("Enabled wohoo!") : QString("Disabled because I like it"));
}
You can of course do also change the tooltip by calling QWidget::isEnabled() and act upon its return value. Since you haven't given any code I can only assume how you toggle your button(s) so that's all I can give you for now.
UPDATE: It was pointed in the comments that tooltips don't work with disabled widgets due not receiving mouse events. Both statements are not true (note that I have used the same tooltip message since due to lack of minimal working example I didn't want to write a whole new project from scratch and used an existing one of mine instead):
Hovering a disabled button triggers the tooltip
Hovering an enabled button triggers the tooltip

How to lose selection focus of a QTextEdit?

I have a readonly QTextEdit. I'm able to select the text and copy it.
What I need to do: When the user is in selection mode(selecting text), if he leaves the area (with the left mouse button still holding) the widget must lose focus and selection focus must end too. When mouse exits out of bounds I want to be similar to mouse release. I tried to set this:
rootWidget->clearFocus();
rootWidget->close();
rootWidget->releaseMouse();
but even though visually the widget seems out of focus I still receive the TextEdit::mouseMoveEvent() of my widget.
I also tried to set focus to a dummy widget. The dummy widget gets focused but my textedit sitll gets mouseMoveEvent().
How can I lose focus of the widget completely without releasing the mouse button?
Thank you for any suggestion!
You can give the focus to something else using QWidget::setFocus(). you should probably clear the selection before changing focus.

How to set cursor when it is in some area?

I have some rectangle link area on my widget. What is the best way to make cursor Qt::PointingHandCursor when it is in this area?
The QWidget class has a cursor property that you can set with the cursor you wish displayed when the mouse is above it.
EDIT:
Without more detail on what you are trying to achieve, I can only assume you're making your life much more difficult than it needs to be. You can create a QLabel widget to handle the link and then place the label on the menubar automatically.
QLabel *link = new QLabel("<a href='http://doc.qt.io'>Qt Documentation</a>");
menuBar()->setCornerWidget(link);
All the text formatting, cursor display and user interactions are handled by existing code in the Qt classes. The only thing you need to do yourself is to handle what happens when the user clicks on the link, that you can do by connecting a slot to the QLabel::linkActivated(const QString &) signal.

Slider reacting on mouse wheel in entire application

By default QSlider reacts on mouse wheel only when cursor is on it. I want to control slider by mouse wheel not matter where the cursor is (of course only when my application has focus).
What's the best way to achieve that?
I just learned that mouse doesn't generate signals. So looks like I need to override wheelEvent in main window and use raise or lower method in it. But I guess that can cause double increment (or decrement) of slider value when mouse is hovering it.
So once again: What's the best way to achieve what I described?
You can override the wheelEvent() in your MainWindow and redirect it to your slider control, that is indeed one option.
Another option is to install an event filter on the qApp instance. This even filter then can check whether the event type is QEvent::Wheel, and when the receiver is not the slider, then again redirect it to the slider. Should work just as well.

PyQt invisible buttons

I am working on a Touchscreen application.
For this I Need to Change the current window if user clicks on the Screen (Position doesn't matter).
For this I Need a to make my button (which is currently the same size as the current window) invisble, so user can see the Labels etc.
Any idea how to make Buttons invisible in PyQt4?
I recommend you not use a button to do this. Instead, either put an event filter on the QApplication instance, so any widgets in your window get events only if you determine they should; OR put a transparent panel widget over the touch area, with a mouse click event handler for that panel. Either method supports arbitrary complexity of widgets inside your touch area (labels and tables to display information etc). Main disadvantage with event filter approach is that all application events (from all threads) will be filtered. This could affect performance (you'd have to test, may not be any noticeable differenc), but it is simpler to implement than the transparent panel.

Resources