我正在创建一个应用程序,它提供节点和将它们连接在一起的线的可视化表示。节点和行都由自定义QWidgets,WidgetNode和WidgetLine表示,比如说。
我已经将WidgetLine实现为一个透明的小部件,它足够大,可以包含该行的起点和终点,以及一个自定义函数来绘制行本身。
我希望如果用户点击该行旁边或右侧,则WidgetLine会获得焦点,但如果他们点击更远的线(但仍然在WidgetLine的几何体所覆盖的矩形区域上),那么点击被WidgetLine完全忽略并传递给下面的小部件。
我首先尝试在WidgetLine上使用自定义focusInEvent()
函数执行此操作,但发现鼠标单击没有在下面传播。然后我尝试将焦点策略设置为Qt::NoFocus
并使用mousePressEvent()
使用setFocus()
在适当的时候手动设置焦点,但鼠标事件仍未传播到上面的小部件,即使我打电话给ignore()
。
最后,我尝试使用此事件过滤器函数
安装事件过滤器来拒绝鼠标事件bool WidgetLineFilter::eventFilter(QObject* object, QEvent* event)
{
assert(object == mCord);
if (event->type() == QEvent::MouseButtonPress)
{
QMouseEvent* e = dynamic_cast<QMouseEvent*>(event);
assert(e);
if (e)
{
QPoint mouseRelativeToParent = mCord->mapToParent(e->pos());
// calculate distance of mouse click to patch cord
QLineF line(mCord->line());
float distance = distanceFromPointToLine(QVector2D(line.p1()), QVector2D(line.p2()), QVector2D(mouseRelativeToParent));
qDebug() << distance;
const float distanceThreshold = 2.f;
if (distance < distanceThreshold)
{
qDebug() << "consuming mouse click for focus";
mCord->setFocus(Qt::MouseFocusReason);
return true;
}
else{
qDebug() << "mousepressevent too far for focus";
return QObject::eventFilter(object, event);
}
}
}
return false;
}
但是这仍然没有将鼠标事件传播给“mousepressevent太远焦点”案例中的父节点。我也试过从这里返回false和true,并在ignore
上调用e
,但下面的小部件没有收到点击。
(注意上述方法在WidgetLine仅在正确的时间获得焦点的意义上起作用,只是下面的小部件在没有获得焦点时没有接收到新闻事件。)
有关如何解决此问题的任何想法?
答案 0 :(得分:0)
将鼠标位置存储在全局变量中。让所有小部件都进入/离开以下事件,并使用它来检查运行func时您所在/附近的小部件。
void QGLWidget::enterEvent(QEvent *)
{
setFocus();
}
void QGLWidget::leaveEvent(QEvent *)
{
clearFocus();
}
答案 1 :(得分:0)
最后,我创建了一个事件过滤器,用于有选择地拦截鼠标事件并将其安装在基本窗口上,并递归地放在基本窗口的每个子窗口小部件上(在创建它们时将其安装在新的子窗口小部件上)。此过滤器使用每个鼠标按下事件调用基本窗口,然后迭代每个WidgetLine,测试是否应该通过此鼠标按下选择它们并在需要时设置焦点。如果它们都测试为false,则过滤器会释放事件,否则过滤器会消耗它。
然后使用
将WidgetLine设置为对鼠标事件透明setAttribute(Qt::WA_TransparentForMouseEvents);
实现这个目标应该比实现这个目标更加麻烦。但是这样做。