QT 实现QGraphicsProxyWidget对象可选择或移动(item管理实现)

2019/02/12 18:13
阅读数 2.2K

上篇博文《QT QGraphicsProxyWidget对象可选择或移动的一些tricks》介绍了实现QT QGraphicsProxyWidget对象可选择或移动的一些小的第三方技巧,但是在实际的项目中一般不那么做。

之前自己学习QGraphicsView研究的还不是很深入,在scene中加入大量的item后,scene框架提供了注入items()、itemAt()等遍历管理其中item的一些操作。

思路:通过对scene中进行鼠标点选获取选择的item(本文主要说的是QGraphicsProxyWidget对象),然后跟随鼠标拖动事件设置其在scene中的位置,终于开阔了思路!

先看一下效果图:

一个QGraphicsProxyWidget嵌入了一个QPushButton;另一个QGraphicsProxyWidget嵌入了一个QCombobox

相关代码如下:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
 
class  GraphicsScene :  public  QGraphicsScene
{
    Q_OBJECT
public :
    GraphicsScene();

protected :
    
void  mousePressEvent(QGraphicsSceneMouseEvent *event);
    
void  mouseMoveEvent(QGraphicsSceneMouseEvent *event);
    
void  mouseReleaseEvent(QGraphicsSceneMouseEvent *event);


private :
    QGraphicsItem   *m_pItemSelected;                   
// 鼠标单选item
    QPoint          m_shiftOrg;                          // 鼠标点选item中位置相对于item原点的偏移量

};


// 鼠标按下获取当前单选中的QGraphicsProxyWidget图元对象
void  GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    qDebug() << 
"scene mouse press" ;
    QGraphicsScene::mousePressEvent(event);

    
if  (event->button() == Qt::LeftButton)
    {
        
// 检测光标下是否有 item
        m_pItemSelected = nullptr;
        foreach (QGraphicsItem *item, items(event->scenePos()))
        {
            
if  (item->type() == QGraphicsProxyWidget::Type)    // 代理Widget
            {
                QGraphicsProxyWidget *proxyWidget = qgraphicsitem_cast<QGraphicsProxyWidget *>(item);
                QPointF point = proxyWidget->mapToScene(QPointF(
0 . 0 0 . 0 ));
                
// 图元左上角在scene中的位置
                qDebug() << point.x();
                qDebug() << point.y();
                
// 当前点击图元点在scene中的位置
                qDebug() << event->scenePos().x();
                qDebug() << event->scenePos().y();
                m_shiftOrg.setX(event->scenePos().x() - point.x());
                m_shiftOrg.setY(event->scenePos().y() - point.y());
                m_pItemSelected = item;
                
break ;
            }
        }
    }

}
// 鼠标移动过程中跟随位置改变
void  GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    qDebug() << 
"scene mouse move" ;
    QGraphicsScene::mouseMoveEvent(event);
    
if (m_pItemSelected != nullptr)
    {
        m_pItemSelected->setPos(event->scenePos().x() - m_shiftOrg.x(), event->scenePos().y() - m_shiftOrg.y());
    }
}
// 鼠标释放后作为最后的位置
void  GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    qDebug() << 
"scene mouse release" ;
    QGraphicsScene::mouseReleaseEvent(event);

    
if (m_pItemSelected != nullptr)
    {
        m_pItemSelected->setPos(event->scenePos().x() - m_shiftOrg.x(), event->scenePos().y() - m_shiftOrg.y());
        m_pItemSelected = nullptr;
    }
}
展开阅读全文
打赏
0
0 收藏
分享
加载中
还有一种方法,就是继承QGraphicsProxyWidget重写鼠标相关事件,调用基类QGraphicsItem的虚事件函数来处理就可以移动控件了,如下内空。具体原理就是跳过QGraphicsProxyWidget重写鼠标相关事件直接用基类QGraphicsItem的虚事件函数,因为QGraphicsProxyWidget重写的事件屏蔽了移动。
class MyQProxyWidget : public QGraphicsProxyWidget
{
public:
MyQProxyWidget();
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
bool eventFilter(QObject *object, QEvent *event) override;
QRectF boundingRect() const override;
QPainterPath shape() const override;
qreal currz=0;
};

void MyQProxyWidget::mousePressEvent(QGraphicsSceneMouseEvent *event)
{

QGraphicsItem::mousePressEvent(event);
}

void MyQProxyWidget::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsItem::mouseMoveEvent(event);

}

void MyQProxyWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{

QGraphicsItem::mouseReleaseEvent(event);
}
2021/08/26 14:39
回复
举报
更多评论
打赏
1 评论
0 收藏
0
分享
返回顶部
顶部