Change style on Hover state of parent QWidget in Qt - c++

I have a composite control in Qt that is a QWidget with a QHBoxLayout containing 3 sub controls (QWidget > QHBoxLayout > 3 QLabels). On one of those controls, which is just a QLabel displaying an icon, I want it to change it's icon when hovering over the entire control. I can get it to work when actually hovering over that icon
QLabel#stateIcon {
image: url(:/icons/stateNormal);
}
QLabel#stateIcon:hover {
image: url(:/icons/stateHover);
}
However, I would like it to show the hover icon when the mouse is anywhere over the whole control.
I tried something like the following:
QLabel#stateIcon::parent:hover {
image: url(:/icons/stateHover);
}
and even
QLabel#stateIcon::parent::parent:hover {
image: url(:/icons/stateHover);
}
Hoping that it would activate on the hover-state of the parent but it does nothing.
Is there a way to do this purely in stylesheets?
If not, is there a way to propagate the parent hover state to it's children in code?

Maybe with an event handler dealing with the QEvent::HoverMove or QEvent::HoverEnter and QEvent::HoverLeave where you can set the attribute Qt::WA_Hover to your label.
I didn't try it but it should work as HoverEnter and HoverLeave causes update() function to be called.

Related

Details Scroll area's setwidget function shows a toolbar

I have a scrollarea and I'm setting a basic QWidget as its widget, However when I do this I get a toolbar on top of the widget I just set;
This is the slot I use to create the QWidget and set it to the scroll area, this happens during runtime and the qwidget is deleted and recreated repeatedly during runtime.
void SlotCreateDetailsWidget()
{
if (m_DetailsWidget == nullptr)
{
m_DetailsWidget = new DetailsWidget(); // QWidget
m_Ui->DetailsScrollArea->setWidget(m_DetailsWidget);
m_DetailsWidget->show();
}
}
What do I need to do to get rid of this toolbar?
From https://doc.qt.io/qt-5/qwidget.html :
A widget without a parent widget is always an independent window
(top-level widget).
What you see depends on the underlying windowing system but you can customize it up to a certain point with void QWidget::setWindowFlag(Qt::WindowType flag, bool on = true) for example. You can also look at https://doc.qt.io/qt-5/qtwidgets-widgets-windowflags-example.html.

Qt: QDialog - activate windows taskbar icon (C++)

I just can not understand one seemingly basic thing.
If we want to show our custom dialog, we can do smth like this:
OurDialog * dlg = new OurDialog; // (this);
dlg->setAttribute(Qt::WA_DeleteOnClose);
dlg->show();
dlg->activateWindow();
hide(); // hide MainWindow
Depending on giving a parent to constructor or not we can make taskbar icon visible or not.
But how to make the icon not only visible but also active?
Moreover, if we move the string
hide(); // hide MainWindow
before
dlg->show();
The taskbar icon will be active, but in this case we'll get a "blinking effect" on showing the dialog.
So is there any possibility to hide MainWindow, show Dialog and make the taskbar icon active?
Thank you!

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().

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);
}
}

Superimpose widgets in Qt designer

I have a Qt application and I would like to superimpose a button on a QTreeWidget using the layouts.
In fact, when I click on an item, I want the button to set visible, and centered above the tree. The button have to stay at the foreground until I click.
Is it possible ?
You could use QStackedLayout and change it's stacking mode to QStackedLayout::StackAll, when you need to show both widgets. Methods would be something like this:
void Widget::showButton()
{
stackedLayout->setStackingMode(QStackedLayout::StackAll);
stackedLayout->setCurrentWidget(widgetWithButton);
}
void Widget::hideButton()
{
stackedLayout->setCurrentWidget(treeWidget);
stackedLayout->setStackingMode(QStackedLayout::StackOne);
}