0

TabletEvents 以鼠标事件的形式出现。

MAC OS Qt 4.8.0 - 4.8.5 的实际值。在任何操作系统上的 Qt 4.7.3 和 Windows 和 Linux 上的 Qt 4.8.0 中都能正常工作。

我有两个 QGraphcisScene 实例和两个 QGraphicsView 实例。相同的类型,但是一个视图有父视图,而另一个视图没有(它也是透明的,用于在桌面上绘制某些东西)。

我正在使用平板电脑(wacom 笔和触控)进行绘画。我处理 QTabletEvents,它仅适用于没有父级的 QGrahicsView 实例(意味着父级==0)。

在与父母的观点上(

QMainWindow->centralWidget->ControlContainerWidget->QStackedLayout->QGraphicsView

) 平板电脑事件不来。他们来得QApplication::eventFilter很好,但不来观看。他们来到QMainWindowmouseEvents。如果我将父级设置为 0,则平板电脑事件可以正常发送。

平板事件的第一个接收者是 QMainWindow。我在里面看到qt_mac_handleTabletEvent

QWidget *qwidget = [theView qt_qwidget];
QWidget *widgetToGetMouse = qwidget;

进而:

`qt_sendSpontaneousEvent(widgetToGetMouse, &qtabletEvent);`

qtabletEvent- 在调用之前创建的不接受事件sendSpontaneousEvent

然后在 QApplication::notify() 内部:

QWidget *w = static_cast<QWidget *>(receiver);
QTabletEvent *tablet = static_cast<QTabletEvent*>(e);
QPoint relpos = tablet->pos();
bool eventAccepted = tablet->isAccepted();
while (w) {
    QTabletEvent te(tablet->type(), relpos, tablet->globalPos(),
                    tablet->hiResGlobalPos(), tablet->device(), tablet->pointerType(),
                    tablet->pressure(), tablet->xTilt(), tablet->yTilt(),
                    tablet->tangentialPressure(), tablet->rotation(), tablet->z(),
                    tablet->modifiers(), tablet->uniqueId());
                    te.spont = e->spontaneous();
    res = d->notify_helper(w, w == receiver ? tablet : &te);
    eventAccepted = ((w == receiver) ? tablet : &te)->isAccepted();
    e->spont = false;
    if ((res && eventAccepted)
         || w->isWindow()
         || w->testAttribute(Qt::WA_NoMousePropagation))
        break;

    relpos += w->pos();
    w = w->parentWidget();
    }
    tablet->setAccepted(eventAccepted);

正如我们所见:

res = d->notify_helper(w, w == receiver ? tablet : &te);

它通过过滤器、布局然后QMainWindow::tabletEven-t调用事件处理。默认实现是event->ignore().

由于 QMainWindow 没有父级,这就是全部。所以平板事件不会出现在 QMainWindow 孩子身上。

然后似乎它是 QWidget *qwidget = [theView qt_qwidget];错误的。不幸的是,我无法调试它...

请给我一些提示...我被卡住了...

4

1 回答 1

0

我花了更多时间比较 Qt 4.8.0 和 4.7.3,现在我发现这是内部 qt 事件调度程序的问题。它将事件发送到 NSWindow (QMainWindow) 而不是 NSView (QGraphicsView)。我没有发现问题出在哪里,但我发现 QMainWindow 从 ::event() 方法返回 false。所以我重新实现了该方法并在那里解析了平板电脑事件:

bool UBMainWindow::event(QEvent *event)
{
    bool bRes = QMainWindow::event(event);

    if (NULL != UBApplication::boardController)
    {
        UBBoardView *controlV = UBApplication::boardController->controlView();
        if (controlV && controlV->isVisible())
        {
            switch (event->type())
            {
            case QEvent::TabletEnterProximity:
            case QEvent::TabletLeaveProximity:
            case QEvent::TabletMove:
            case QEvent::TabletPress:
            case QEvent::TabletRelease:
                {
                    return controlV->directTabletEvent(event);
                }
            }
        }
    }
    return bRes;
}

问题是:我需要对应用程序中的任何控件使用平板电脑,所以我需要确定 QGraphicsView 何时在鼠标光标下:

bool UBBoardView::directTabletEvent(QEvent *event)
{
    QTabletEvent *tEvent = static_cast<QTabletEvent *>(event);
    tEvent = new QTabletEvent(tEvent->type()
        , mapFromGlobal(tEvent->pos())
        , tEvent->globalPos()
        , tEvent->hiResGlobalPos()
        , tEvent->device()
        , tEvent->pointerType()
        , tEvent->pressure()
        , tEvent->xTilt()
        , tEvent->yTilt()
        , tEvent->tangentialPressure()
        , tEvent->rotation()
        , tEvent->z()
        , tEvent->modifiers()
        , tEvent->uniqueId());

    if (geometry().contains(tEvent->pos()))
    {
        if (NULL == widgetForTabletEvent(this->parentWidget(), tEvent->pos()))
        {
            tabletEvent(tEvent);
            return true;
        }
    }
    return false;
}

我还需要停止为 QGraphicsView 孩子处理平板电脑事件。

QWidget *UBBoardView::widgetForTabletEvent(QWidget *w, const QPoint &pos)
{
    Q_ASSERT(w);


    UBBoardView *board = qobject_cast<UBBoardView *>(w);

    QWidget *childAtPos = NULL;

    QList<QObject *> childs = w->children();
    foreach(QObject *child, childs)
    {
        QWidget *childWidget = qobject_cast<QWidget *>(child);
        if (childWidget)
        {
            if (childWidget->isVisible() && childWidget->geometry().contains(pos))
            {
                QWidget *lastChild = widgetForTabletEvent(childWidget, pos);

                if (board && board->viewport() == lastChild)
                    continue;

                if (NULL != lastChild)
                    childAtPos = lastChild;
                else
                    childAtPos = childWidget;

                break;
            }
            else
                childAtPos = NULL;
        }
    }
    return childAtPos;
}

也许当我有更多时间时——我会更深入地研究 qt 并完全解决这个问题。

于 2013-03-18T07:02:39.543 回答