2012-03-26 68 views
8

使用例:これはかなり一般的な問題です。 QMdiAreaを持つ通常のQMainWindowには、QGraphicsViewを持つmdiChildが存在します。このビューにはQGraphicsSceneとQGraphicsItemsが表示されます。これらの項目の1つを右クリックすると項目が選択(フォーカス)され、コンテキストメニューが開きます。これは画面座標QGraphicsSceneMouseEvent::screenPos()に配置すると便利です。これは期待どおりに動作しています。QGraphicsItemのスクリーン位置を見つける

ここで、ユーザーがキー(例:Qt :: Key_Menu)を押したときに同じコンテキストメニューを表示したいとします。私は選択された(焦点を合わせた)アイテムを知っています、私はシーンを表示するビューを知っています。

だから私の質問は次のとおりです。
シーン内QGraphicsItemの可視表現の(グローバル、スクリーン座標で)位置を取得するための正しい方法は何ですか?ここで

働いていないものです:

QGraphicsItem *item = ...; // is the currently selected item next to which the context menu shall be opened 
QGraphicsScene *scene = ...; // is the scene that hosts the item 
QGraphicsView *graphicsView = ...; // is the view displaying the scene, this inherits from QWidget 

// get the position relative to the scene 
QPointF sp = item->scenePos(); 
// or use 
QPointF sp = item->mapToScene(item->pos()); 

// find the global (screen) position of the item 
QPoint global = graphicsView->mapToGlobal(graphicsView->mapFromScene(sp)); 

// now 
myContextMenu.exec(global); 
// should open the context menu at the top left corner of the QGraphicsItem item, but it goes anywhere 

The doc says: あなたは、ビューポート内のアイテムがどこにあるかを知りたい場合は、あなたがQGraphicsItemを呼び出すことができます:: mapToScene()の項目に、そしてQGraphicsView: :ビューのmapFromScene()。
これはまさに私がやっていることですよね?


ちょうどにヒントa thread in a german forumつまずい:でも

QGraphicsView *view = item->scene()->views().last(); 

またはよりよい:

QGraphicsView *view; 
foreach (view, this->scene()->views()) 
{ 
    if (view->underMouse() || view->hasFocus()) break; 
} 
// (use case in the forum thread:) // QMenu *menu = new QMenu(view); 

それは私の質問に、より一般的な答えを許すかもしれません使用して...

+0

私は回答を投稿しようとしていましたが、ドキュメントを再読み込みすることで、私はあなたの分析に同意したと思います。QGraphicsView :: mapFromSceneは、ビューポートの座標(チェック価値がある)を与える必要があります。 MDI子のウィジェットのmapToGlobalに潜在的なバグがある場合にのみ質問があります。 –

+0

@JamesTurnerだから、あなたの最初の推測は何でしょうか(これはあなたの回答で書かれたでしょう)? –

答えて

6

解決策が見つかりました。
QGraphicsItemが画面に表示されている必要があります。 (ビューはシーンの他のいくつかのポイントを示しているので、それが表示されていないおそらく場合は、1がビューのビューポートの矩形にポイントを抑えることができます。)

// get the screen position of a QGraphicsItem 
// assumption: the scene is displayed in only one view or the first view is the one to determine the screen position for 
QPoint sendMenuEventPos; // in this case: find the screen position to display a context menu at 
QGraphicsItem *pFocusItem = scene()->focusItem(); 

if(scene() != NULL // the focus item belongs to a scene 
    && !scene()->views().isEmpty() // that scene is displayed in a view... 
    && scene()->views().first() != NULL // ... which is not null... 
    && scene()->views().first()->viewport() != NULL // ... and has a viewport 
    ) 
{ 
    QGraphicsView *v = scene()->views().first(); 
    QPointF sceneP = pFocusItem->mapToScene(pFocusItem->boundingRect().bottomRight()); 
    QPoint viewP = v->mapFromScene(sceneP); 
    sendMenuEventPos = v->viewport()->mapToGlobal(viewP); 
} 

if(sendMenuEventPos != QPoint()) 
{ 
    // display the menu: 
    QMenu m; 
    m.exec(sendMenuEventPos); 
} 

ビューのCOORDSをマッピングするためのビューのビューポートを使用することが重要ですグローバル・コーズへ。

コンテキストメニューキー(Qt :: Key_Menu)の検出は、 "メイン" QGraphicsItemのkeyPressEvent()(myプログラムの構造上)で行われます。

+1

イベント中、ビューのビューポートは 'QGraphicsSceneEvent :: widget()'でシーンに公開されます。 'QWidget :: isAncestorOf(event-> widget())'を使って、最初のビューを取るのではなく、正しいビューを見つけることができます。 – hmn

+0

アプリケーションが常にフルスクリーンで実行されない限り、 'mapToGlobal'を使用する代わりに、' sendMenuEventPos = v-> viewport() - > mapTo(mainWindow、viewP);を使用して 'QMainWindow'にマップする方が良いでしょう。 – vsz

1

コードが正しいようです。しかし、コンテキストメニューの作成には問題があるかもしれません。

QContextMenuの親をMainWindowに設定しましたか?

あなたの場合は問題があると思います。

Good Luck !!

1

暗闇の中でちょうど刺すが、このhttp://www.qtcentre.org/threads/36992-Keyboard-shortcut-event-not-receivedを見てください。

Qtのドキュメントを見ると、QGraphicsViewを使用すると、ショートカットに関していくつかの例外的な動作が発生する可能性があります。

あなたが望む結果を達成するための規範的な方法があるかのように見えます。

コンテキストメニュー、ショートカット、およびQGraphicsViewの実装方法に応じて、QGraphicsViewのQt :: ContextMenuPolicyを適切に設定し、メニューを別々に作成して呼び出す必要があります。

私はまもなくまったく同じことをする必要があるので、この質問にはかなり興味があります!

+0

'Qt :: ActionsContextMenu'は見た目が光っています。私はそれを調べるでしょうが、それが助けになるとは確信していません。私の一般的な問題は、キーボードの入力よりも配置に関するものです(私はどこからでもその関数を呼び出すことができます)。 –

+0

私はそれが関連しているかどうかにかかわらず、どのように実装したかによって異なります。私はまた、興味深いドキュメンテーションに次のオーバーロードされた 'exec'関数定義があることを発見しました:http://doc.qt.nokia.com/4.7-snapshot/qmenu.html#exec-3。これは奇妙な静的メソッドのようですが、 "...親がQGraphicsViewに埋め込まれている"ときにQPointで十分ではない可能性を暗示しています。それは少し神秘的です。 –

関連する問題