假设结构如下:
MainWindow
--->MySpecialWidget
|-->QLineEdit
|-->QSpinBox
|-->QPushButton
---><Basically any other Widget accepting QMouseEvent>
点击上面提到的任何一个将导致其各自的特性被激活,QMouseEvent被接受和丢弃。
我想在我的主窗口内以通用的方式对任何鼠标点击作出反应。更具体地说,我想阻止基本的Qt小部件接受QMouseEvent
,同时仍然以他们通常的方式对它做出反应。不接受应该只发生在他们是MySpecialWidget
的孩子的时候。由于QMouseEvent
被接受为两层深,我的主窗口不能通过直接的eventFilter
访问它。
我当前的解决方案(简化):
void MySpecialWidget::eventFilter(QObject *o, QEvent *e)
{
if(e->type() == QEvent::MouseButtonPress)
{
QMouseEvent *mE = static_cast<QMouseEvent*>(e);
QMouseEvent newMouseEvent = new QMouseEvent(QMouseEvent::MouseButtonPress, mE->pos(), mE->button(), mE->buttons(), mE->modifiers());
qApp->notify(this, &newMouseEvent);
// Check how this handled the copied Mouseevent
return /*result of check*/;
}
return Base::eventFilter(o, e);
}
我还在考虑将我的MainWindows
事件过滤器附加到所有相关的内容,但这听起来像是在更大的项目中处理的噩梦。
有没有人做过类似的事情,或者你知道是否有可能以另一种方式实现?我当前的解决方案可以接受吗?
编辑:我注意到对于不同的QWidgets
,当QMouseEvent
被"吃掉"时,你会得到不同的行为。例如,MySpecialWidget
可以过滤QLineEdit
的QMouseEvents
,但不能过滤QSpinBox
,因为它本身包含QLineEdit
。我发现这个库的这种行为非常令人恼火。
Edit2澄清:虽然vahanchos的评论将解决问题,我正在寻找一个解决方案,可以与MySpecialWidget
工作,而不触及QApplication
或包含的类。
对我的方法或我的请求的可行性的任何评论将是非常感谢的!
我希望我理解了这个问题背后的关键。
基本上,如果你的问题是"如何捕获各种类型的大量小部件的事件,包括那些由子小部件(如QSpinbox > QLineEdit
)组成的事件,而不使其成为管理的噩梦",你可以使用QObject::findChildren
。
更准确地说,在调用ui->setupUi()
之后将它添加到您的窗口构造函数中,它将捕获MySpecialWidget
实例下的所有内容:
auto children = ui->mySpecialWidget->findChildren<QWidget*>(QString(), Qt::FindChildrenRecursively);
for (QWidget* w : children)
w->installEventFilter(ui->mySpecialWidget);
您可能已经理解,这将探索它的所有子部件(递归地),并将实例安装为所有子部件的公共事件过滤器。
注:
MySpecialWidget::eventFilter
的实现有问题。它应该返回一个布尔值。重写这个方法通常是这样做的:
bool MySpecialWidget::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::MouseButtonRelease)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
//do something
return true;
}
else // standard event processing
return QObject::eventFilter(obj, event);
}
我记得做过类似的事情来简化大量切换鼠标事件。它基本上是由一个"看不见的盾牌"组成的。控件悬停在我想要阻止的控件上。当可见时,这个视图捕捉到所有事件;不然,他们就往前走,"经过"了。它。
你可以使用QStackedLayout
来实现它,把盾放在堆栈的顶部,并将堆叠模式设置为StackAll
。当捕获事件时,您可以处理它们,然后不接受事件,让它通过。
这里的主要缺点是它会改变你的MySpecialWidget
是如何设计的,由于堆叠布局,但这将取决于你的UI架构。