0

TabletEvents はマウス イベントとして提供されます。

MAC OS Qt 4.8.0 - 4.8.5 の実際。任意の OS の Qt 4.7.3 と、Windows および Linux の Qt 4.8.0 で正常に動作します。

QGraphcisScene の 2 つのインスタンスと QGraphicsView の 2 つのインスタンスがあります。同じタイプですが、1 つのビューには親があり、もう 1 つのビューにはありません (また、透明で、デスクトップ上に何かを描画するために使用されます)。

ペイントにはタブレット(ワコムペンとタッチ)を使用しています。私は QTabletEvents を処理しますが、親を持たない QGrahicsView インスタンスに対してのみ機能します (parent==0 を意味します)。

親を持つビュー(

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

)タブレットイベントは来ません。彼らはQApplication::eventFilter元気になりますが、見えません。彼らは のようにQMainWindowなりmouseEventsます。親を 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 には Parent がないため、すべてです。そのため、タブレット イベントは QMainWindow の子には来ません。

それからそれは QWidget *qwidget = [theView qt_qwidget];間違って動作しているようです。残念ながら、私はそれをデバッグすることはできません...

ヒントをください...私は立ち往生しています...

4

1 に答える 1

0

Qt 4.8.0 と 4.7.3 の比較に多くの時間を費やしましたが、内部の qt イベント ディスパッチャの問題であることがわかりました。NSView (QGraphicsView) ではなく、NSWindow (QMainWindow) にイベントを送信します。どこに問題があるのか​​わかりませんでしたが、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 に答える