查找QGraphicsItem的屏幕位置 [英] Find screen position of a QGraphicsItem

查看:3160
本文介绍了查找QGraphicsItem的屏幕位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用案例:这应该是一个相当普遍的问题。在一个正常的QMainWindow与QMdiArea生活一个mdiChild与一个QGraphicsView。此视图显示一个QGraphicsScene与QGraphicsItems里面。右键单击其中一个项目选择(聚焦)项目,并打开一个上下文菜单,它方便地放置在屏幕坐标 QGraphicsSceneMouseEvent :: screenPos()



现在我想在用户按下一个键时显示相同的上下文菜单(例如Qt :: Key_Menu)。我知道选择的(聚焦的)项目,我知道显示场景的视图。



所以我的问题是: $ b在场景中获取QGraphicsItem的可见表示的位置(全局,屏幕坐标)的正确方法是什么?



这里是不工作:

  QGraphicsItem * item = ... //是当前选择的项目,在其旁边将打开上下文菜单
QGraphicsScene * scene = ...; //是承载项目的场景
QGraphicsView * graphicsView = ...; //是显示场景的视图,它继承自QWidget

//获取相对于场景的位置
QPointF sp = item-> scenePos();
//或使用
QPointF sp = item-> mapToScene(item-> pos());

//查找项目的全局(屏幕)位置
QPoint global = graphicsView-> mapToGlobal(graphicsView-> mapFromScene(sp));

// now
myContextMenu.exec(global);
//应该打开QGraphicsItem项目左上角的上下文菜单,但它可以到任何地方

文件说:
如果你想知道项目在视口中的位置,你可以在项目上调用QGraphicsItem :: mapToScene(),然后在视图上调用QGraphicsView :: mapFromScene()。

这正是我在做什么,是吗?






刚刚偶然发现德国论坛中的主题提示:

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

甚至更好:

  QGraphicsView * view; 
foreach(view,this-> scene() - > views())
{
if(view-> underMouse()|| view-> hasFocus打破;
}
//(在论坛主题的用例)// QMenu * menu = new QMenu(view);

使用这个可能允许更广泛地回答我的问题...

解决方案

我发现了一个有效的解决方案。

QGraphicsItem必须在屏幕上可见。
(可能如果它不可见,因为视图显示了场景的其他点,可以限制视图的视口的rect。)

  //获取QGraphicsItem的屏幕位置
//假设:场景只显示在一个视图中,或者第一个视图是确定
的屏幕位置的视图QPoint sendMenuEventPos; //在这种情况下:找到屏幕位置以在
上显示上下文菜单QGraphicsItem * pFocusItem = scene() - > focusItem();

if(scene()!= NULL //焦点项目属于场景
&&!scene() - > views()。isEmpty场景显示在视图...
&&&& scene() - > views()。first()!= NULL // ...不是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())
{
//显示菜单:
QMenu m;
m.exec(sendMenuEventPos);
}

重要的是使用视图的视口将视图坐标映射到全局坐标。



检测上下文菜单键(Qt :: Key_Menu)发生在 keyPressEvent() mainQGraphicsItem(由于我的程序的结构)。


Use case: This should be a fairly common problem. In a normal QMainWindow with QMdiArea lives an mdiChild with a QGraphicsView. This view displays a QGraphicsScene with QGraphicsItems inside. A right-click at one of these items selects (focusses) the item and opens a context menu, which is conveniently placed at the screen coordinates QGraphicsSceneMouseEvent::screenPos(). This is working as expected.

Now I'd like to show the same context menu when the user presses a key (e.g. Qt::Key_Menu). I know the selected (focussed) item, I know the view which displays the scene.

So my question is:
What is the correct way to get the position (in global, screen coordinates) of the visible representation of a QGraphicsItem within a scene?

Here is what's not working:

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: If you want to know where in the viewport an item is located, you can call QGraphicsItem::mapToScene() on the item, then QGraphicsView::mapFromScene() on the view.
Which is exactly what I'm doing, right?


Just stumbled upon a thread in a german forum that hints to:

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

or even nicer:

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

Using that might allow a more generalized answer to my question...

解决方案

I found a working solution.
The QGraphicsItem must be visible on the screen. (Probably if it's not visible because the view shows some other point of the scene, one could restrain the point to the view's viewport's rect.)

// 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);
}

It is important to use the view's viewport for mapping the view coords to global coords.

The detection of the context menu key (Qt::Key_Menu) happens in the keyPressEvent() of the "main" QGraphicsItem (due to the structure of my program).

这篇关于查找QGraphicsItem的屏幕位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆