PDA

View Full Version : Can't catch mouse-click in MainWindow's subclassed child widgets from my MainWindow



alketi
7th February 2018, 20:01
I'm unable to successfully capture a mouse click in my QMainWindow for subclassed child widgets, such those that live inside a subclassed QTabWidget, like buttons, QTextEdits, etc.

I install a mousePressEvent() filter on the QMainWindow class.



void MyTool::mousePressEvent(QMouseEvent *event)
{
qDebug() << "mousePressEvent";
QMainWindow::mousePressEvent(event);
}


I also pass the QMainWindow parent pointer to the subclassed child QTabWidget.

When I click around in the UI, I get a successful mouse press event if I click on whitespace (such as the tab widget frame). Good.

But I do not get a mouse press event if I click on any QWidget inside the QTabWidget, such as buttons or a text edit. These widgets would (I suppose) be grand-children of the QMainWindow.

Shouldn't I be able to install a mouse event filter on the parent and receive events for a click on any subclassed descendant? Or, do I need event filters at all child levels?

d_stranz
8th February 2018, 17:30
QMainWindow::mousePressEvent(event);

Why do you think that this line of code will result in the event being passed to your QMainWindow instance? QMainWindow::mousePressEvent() is not a static function; it must be called through a pointer to a QMainWindow. The only way this could be correct syntax would be if MyTool was derived from QMainWindow.


I install a mousePressEvent() filter on the QMainWindow class.

This code does not install an event filter on anything. It overrides and re-implements the virtual mousePressEvent() of whatever class MyTool is derived from. A Qt "event filter" is a specific type of function that can be implemented in one class instance to intercept events generated for an instance of another class.

Uwe
8th February 2018, 19:31
Or, do I need event filters at all child levels?
Input events are processed bottom up - until they are accepted. So yes, when clicking on widgets like buttons the parent does not get them anymore.
Installing event filters is one solution, another one is to overload QApplication::notify if you want to process the event before.

In Qt/Quick there is a QQuickItem::childMouseEventFilter, that is made for detecting gestures.
I havn't checked how gestures are done for widgets, but maybe you find something in this area that can be used for your purposes.

HTH,
Uwe

alketi
9th February 2018, 18:29
Why do you think that this line of code will result in the event being passed to your QMainWindow instance? QMainWindow::mousePressEvent() is not a static function; it must be called through a pointer to a QMainWindow. The only way this could be correct syntax would be if MyTool was derived from QMainWindow.

Well, I think that this line of code will be passed to my QMainWindow instance because MyTool is derived from QMainWindow, as you stated in your second sentence.

Thank you Uwe. Your explanation makes perfect sense.

d_stranz
11th February 2018, 17:47
Well, I think that this line of code will be passed to my QMainWindow instance because MyTool is derived from QMainWindow

So then why did you ask your question this way?

"I'm unable to successfully capture a mouse click in my QMainWindow for subclassed child widgets, such those that live inside a subclassed QTabWidget, like buttons, QTextEdits, etc."

None of these widgets are derived from QMainWindow. You then go on to talk about "MyTool", which based on the above, I assumed was some child widget embedded in a tab widget somewhere.

What Uwe says is correct - if a child widget accepts a mouse event, then it gets eaten and doesn't pass further up the chain of parents. If you need the actual mouse event, then writing an event filter for your QMainWindow class and installing it on the child widget is one solution. It is less brute-force than using QApplication::notify().

If you don't need the actual muse events, it might be cleaner to try to use signals generated by the child widgets or subclass the child widget, override the mouse event, and emit a signal when it occurs.