我正在使用qt creator制作计算器。有一个默认的主窗口形式有gui。在mainwindow.cpp中,我设置了setMouseTracking(true),以便在单击时获取鼠标坐标。但是,只有在主窗口窗体中的任何按钮外部进行单击时,才能获得鼠标坐标。我想这与以下事实有关:当点击一个按钮时,已经生成某种类型的鼠标事件来处理该点击。 我需要在按钮内单击时获取坐标。我该怎么做?
答案 0 :(得分:1)
首先要做的是:这是一个坏主意:)
您要做的是捕获发送到子对象的事件。一种方法是重新实现子对象的事件处理程序。但是,当您使用设计器构建界面时,这会变得有点困难。您必须推广所有小部件以重新实现它们的版本。
另一种方法是使用Qt的“偶数过滤”功能。您实现了一个基于QObject的类,它实现了一个通用的事件处理函数。然后在目标对象上将此对象安装为“事件过滤器”。一个简单的偶数过滤器类看起来像这样;
class Filter : public QObject
{
protected:
bool eventFilter(QObject *obj, QEvent *ev)
{
// obj : original receiver of the event
// ev : any event that is sent to 'obj'
QObject::event(obj, ev);
}
};
及其用法:
Filter filterObject;
targetObject.installEventFilter(filterObject);
通常,您必须将此事件过滤器安装到用户界面中的所有对象(窗口小部件)。但是,如果您将此过滤器安装到QApplication
实例,则不会逐个进行,而是会捕获应用程序中的所有事件。捕获后,您可以按类型和创建者过滤事件。
这是一个更完整的示例,它将捕获应用程序中的所有鼠标按下事件;
class ClickFilter : public QObject
{
protected:
bool eventFilter(QObject *obj, QEvent *ev)
{
if (ev->type() == QEvent::MouseButtonPress && obj->inherits("QWidgetWindow"))
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(ev);
qDebug() << "clicked:" << mouseEvent->pos();
}
return QObject::eventFilter(obj, ev);
}
};
您应该在QApplication
实例上安装此事件过滤器对象,大概在main
函数中;
QApplication a(argc, argv);
ClickFilter cf;
a.installEventFilter(&cf);
这将捕获应用程序中的所有事件(包括所有窗口 - 如果您的应用程序有多个主窗口),然后按类型和创建者对象类型过滤它们。
但是这段代码存在问题。我使用QWidgetWindow
类型来检查事件发起者。那是因为如果一个事件没有被子窗口小部件处理,它会传播到它的父窗口。因此,在某些情况下,同一点击事件会多次调用ClickFilter::eventFilter
。我选择了QWidgetWindow
因为它看起来像是一种简单的方法。问题是; QWidgetWindow
是内部Qt类型。在您的应用程序中使用它不是一个好主意。我确信还有另一种防止重复的方法。
更重要的是,在QApplication
实例上安装事件过滤器并不是一个好主意,它可能会导致性能问题。但另一方面,在我的应用程序中,我使用这种方法在所有应用程序中轻松地将工具栏按钮的键盘快捷键添加到工具提示中。你可以看到它here。