[SOLVED] QWidget - WA_TransparentForMouseEvents but not for children
-
I have a QWidget that is on top of a QwtPlot.
I made the QWidget transparent for mouse events so that the plot can receive the mouseMoved event underneath.
The problem is this:
I also have a child QWidget inside this parent widget that would like to receive mouseEvent. but since the parent has the flag on, the child cannot receive any mouse event.Example in action :
https://www.dropbox.com/s/t8ao6asilr8gt75/mouseEventProblem.png?dl=0
(QSpinBox can't receive anymore focus and be edited since the parent QWidget has the attribute "WA_TransparentForMouseEvents ")Here is my code for reference, I tried bunch of things for 1-2hrs (eventFilter, etc.) but seems like it's not possible to have child receive any mouse event if the parent is transparentForMouseEvent
QWidget *widgetMsg = new QWidget(this); QVBoxLayout *vlayout = new QVBoxLayout(this); vlayout->setMargin(0); vlayout->setSpacing(0); QSpacerItem *spacer = new QSpacerItem(1, 1, QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); labelMsgInterval = new FaderLabel(this); labelMsgInterval->setStyleSheet("background-color : rgba(1,1,1,140);" "border-radius: 15px;" "border: 1px solid beige;"); labelMsgInterval->setMinimumHeight(60); labelMsgInterval->setMaximumHeight(90); labelMsgInterval->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); labelMsgInterval->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); labelMsgInterval->hide(); QWidget *widgetTopForSpinBox = new QWidget(this); QHBoxLayout *hlayout = new QHBoxLayout(this); hlayout->setMargin(0); hlayout->setSpacing(0); hlayout->setContentsMargins(0,0,0,0); QSpinBox *spinBoxDifficulty = new QSpinBox(this); spinBoxDifficulty->setButtonSymbols(QAbstractSpinBox::PlusMinus); spinBoxDifficulty->setMinimum(-100); spinBoxDifficulty->setMaximum(100); spinBoxDifficulty->setSuffix("%"); //±% spinBoxDifficulty->setFixedHeight(30); spinBoxDifficulty->setFixedWidth(55); spinBoxDifficulty->setValue(0); spinBoxDifficulty->setStyleSheet("background-color : rgb(35,35,35); color : white;"); spinBoxDifficulty->setKeyboardTracking(false); connect(spinBoxDifficulty, SIGNAL(valueChanged(int)), this, SIGNAL(workoutDifficultyChanged(int))); hlayout->setAlignment(Qt::AlignRight | Qt::AlignTop); hlayout->addWidget(spinBoxDifficulty); widgetTopForSpinBox->setLayout(hlayout); vlayout->addWidget(widgetTopForSpinBox); vlayout->addSpacerItem(spacer); vlayout->addWidget(labelMsgInterval, Qt::AlignBottom); QFont fontBig; fontBig.setPointSize(20); labelMsg->setFont(fontBig); labelMsgInterval->setFont(fontBig); widgetMsg->setLayout(vlayout); //------------------------------ widgetCanvas = this->canvas(); QGridLayout *gridLayout = new QGridLayout(this); gridLayout->setMargin(0); gridLayout->setSpacing(0); gridLayout->setContentsMargins(0,0,0,0); gridLayout->addWidget(labelMsg, 0, 0, 1, 1); gridLayout->addWidget(widgetMsg, 0, 0, 1, 1); widgetCanvas->setLayout(gridLayout); widgetMsg->installEventFilter(this); //tried this option, no success.. // widgetTopForSpinBox->setAttribute(Qt::WA_TransparentForMouseEvents, false); // spinBoxDifficulty->setAttribute(Qt::WA_TransparentForMouseEvents, false); widgetMsg->setAttribute(Qt::WA_TransparentForMouseEvents, true); labelMsg->setAttribute(Qt::WA_TransparentForMouseEvents, true); labelMsgInterval->setAttribute(Qt::WA_TransparentForMouseEvents, true);
Other thread with no clear solution :
http://stackoverflow.com/questions/5563862/how-to-pass-click-event-to-sibling-underneath-in-qt -
Hi,
How should that widget work ? Is it always there ? Should it appear at some point ?
-
The QWidget on top of the Qwtplot is always there and contains QLabel that are invisible and set to Visible when I need to display a message on top of the QwtPlot. The QSpinBox is always there and always visible.
-
In that case, why not make it independent of your other widget ? Move it at the right position on top of that "information widget" so you don't need to fiddle with event transparency for it
-
Thanks SGaist! Finally got it to work, I add to rethink the whole layout .
Now I have a QwtPlotPicker with custom text shown when my cursor is on the graph (x,y), and a normal cursor when I'm on the SpinBox. Had to do an event filter because the text would not clear on the cursor when going on the QSpinBox.Sharing the code in case it helps someone.
QWidget *widgetMsg = new QWidget(this); QVBoxLayout *vlayout = new QVBoxLayout(this); vlayout->setMargin(0); vlayout->setSpacing(0); vlayout->setAlignment(Qt::AlignBottom); labelMsgInterval = new FaderLabel(this); labelMsgInterval->setStyleSheet("background-color : rgba(1,1,1,140);" "border-radius: 15px;" "border: 1px solid beige;"); labelMsgInterval->setMinimumHeight(60); labelMsgInterval->setMaximumHeight(90); labelMsgInterval->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); labelMsgInterval->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); labelMsgInterval->hide(); vlayout->addWidget(labelMsgInterval); QSpinBox *spinBoxDifficulty = new QSpinBox(this); spinBoxDifficulty->setButtonSymbols(QAbstractSpinBox::PlusMinus); spinBoxDifficulty->setMinimum(-100); spinBoxDifficulty->setMaximum(100); spinBoxDifficulty->setSuffix("%"); //±% spinBoxDifficulty->setFixedHeight(30); spinBoxDifficulty->setFixedWidth(55); spinBoxDifficulty->setValue(0); spinBoxDifficulty->setStyleSheet("background-color : rgb(35,35,35); color : white;"); spinBoxDifficulty->setKeyboardTracking(false); spinBoxDifficulty->setCursor(Qt::ArrowCursor); connect(spinBoxDifficulty, SIGNAL(valueChanged(int)), this, SIGNAL(workoutDifficultyChanged(int))); QFont fontBig; fontBig.setPointSize(20); labelMsg->setFont(fontBig); labelMsgInterval->setFont(fontBig); widgetMsg->setLayout(vlayout); //------------------------------ widgetCanvas = this->canvas(); QGridLayout *gridLayout = new QGridLayout(this); gridLayout->setMargin(0); gridLayout->setSpacing(0); gridLayout->setContentsMargins(0,0,0,0); gridLayout->addWidget(spinBoxDifficulty, 0, 1, 1, 1); gridLayout->addWidget(labelMsg, 0, 0, 2, 2); gridLayout->addWidget(widgetMsg, 0, 0, 2, 2); widgetCanvas->setLayout(gridLayout); spinBoxDifficulty->installEventFilter(this); widgetMsg->setAttribute(Qt::WA_TransparentForMouseEvents, true); labelMsg->setAttribute(Qt::WA_TransparentForMouseEvents, true); labelMsgInterval->setAttribute(Qt::WA_TransparentForMouseEvents, true);
Event filter
bool WorkoutPlot::eventFilter(QObject *watched, QEvent *event) { QSpinBox *ptrSpinBox = qobject_cast<QSpinBox*>(watched); if (ptrSpinBox != NULL) { if (event->type() == QEvent::HoverEnter) { d_picker->setEnabled(false); } else if (event->type() == QEvent::HoverLeave) { d_picker->setEnabled(true); } } return false; }
-
Thanks for sharing !