【问题标题】:how to get qlabel to follow cursor in scene如何让qlabel在场景中跟随光标
【发布时间】:2014-02-26 02:23:43
【问题描述】:

我有一个图像存储在场景中的 Qlabel 中。我想让 Qlabel 图像跟随光标在场景内移动的位置。我已经尝试了 QGraphicsSceneMouseMove,但还没有接近。

    void scene::mouseMoveEvent(QGraphicsSceneMouseEvent /*mouseEvent*/)
    {

        QPointF P1 = ui->tankarmplay1->mapFromParent(QCursor.pos()); 
        int x = P1.x();
        int y = P1.y();
        ui->tankarmplay1->setGeometry(x,y, 50, 50);

    }

【问题讨论】:

    标签: c++ qt cursor qlabel


    【解决方案1】:

    更新:添加了指向鼠标的QGraphicsLineItem。这可以用使用QGraphicsItemGroup 的某种炮塔的完整图代替,并使用相同的旋转计算。

    以下链接介绍了您应该熟悉的许多内容:

    http://qt-project.org/doc/qt-5/graphicsview.html

    http://qt-project.org/doc/qt-5/application-windows.html

    void scene::mouseMoveEvent(QGraphicsSceneMouseEvent * e /*mouseEvent*/)
    {
    
        // QPointF P1 = (e->pos()); 
        // int x = P1.x();
        // int y = P1.y();
        // ui->tankarmplay1->setGeometry(x, y, 50, 50);
    
        ui->tankarmplay1->move((int) e->pos().x(), (int) e->pos().y());
    }
    

    http://qt-project.org/doc/qt-5/qgraphicsscenemouseevent.html#pos

    我没有亲自使用过QCursor。我认为当您手边有鼠标事件的pos 信息时,这是一种非常全面的查找鼠标的方法。如果您使用 QCursor,您可能需要使用 mapFromGlobal 而不是 mapFromParent

    http://qt-project.org/doc/qt-5/qcursor.html#details

    http://qt-project.org/doc/qt-5/qcursor.html#pos

    这是我在使用特定的 QGraphicsSceneMouseEvent 方法之前写的。

    为了让这些工作我不得不使用mapToScene() 来获得可能匹配的坐标。

    How to draw a point (on mouseclick) on a QGraphicsScene?

    在QWidget的pos属性中,一般用move()修改。 setGeometry 也可以,但您最终也会大量引用 widthheight

    http://qt-project.org/doc/qt-4.8/qwidget.html#pos-prop

    http://qt-project.org/doc/qt-4.8/qwidget.html#mouseTracking-prop

    更新:很棒的例子,展示了在场景中和场景外使用的鼠标跟踪 注意,使用 QGraphicsTextItem 可能比使用 QLabel + QGraphicsProxyWidget 在场景中移动一些文本更干净。

    小部件.h

    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    #include <QFrame>
    #include <QLabel>
    #include <QPointF>
    #include "mygraphicsscene.h"
    #include <QGraphicsView>
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    public:
        Widget(QWidget *parent = 0);
        ~Widget();
        qreal map(const qreal & x1, qreal x, const qreal & x2, const qreal & y1, const qreal & y2);
    public slots:
        void on_sceneMouseMove(QPointF);
    private:
        QLabel * m_label;
        MyGraphicsScene * m_scene;
        QGraphicsView * m_view;
        QFrame * m_labelContainer;
    };
    
    #endif // WIDGET_H
    

    widget.cpp

    #include "widget.h"
    #include <QGraphicsView>
    #include "mygraphicsscene.h"
    #include <QVBoxLayout>
    #include <QLabel>
    #include <QDebug>
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
    {
        QVBoxLayout * vbox = new QVBoxLayout;
    
        m_view = new QGraphicsView;
    
        m_scene = new MyGraphicsScene;
    
        m_view->setScene(m_scene);
    
        m_view->setMouseTracking(true);
        m_scene->setSceneRect(-300,-300, 600, 600);
        m_view->fitInView(m_scene->sceneRect());
    
        vbox->addWidget(m_view, 1);
    
        m_labelContainer = new QFrame;
        m_labelContainer->setFrameShape(QFrame::Box);
        m_label = new QLabel("Tracking Label");
        m_labelContainer->setFixedSize(300, 300);
        m_label->setParent(m_labelContainer);
    
        vbox->addWidget(m_labelContainer, 1);
    
        QObject::connect(m_scene, SIGNAL(mouseMoved(QPointF)),
                         this, SLOT(on_sceneMouseMove(QPointF)));
    
        this->setLayout(vbox);
    }
    
    void Widget::on_sceneMouseMove(QPointF pt)
    {
        QPointF pt2;
        pt2.setX(map(m_scene->sceneRect().left(), pt.x(), m_scene->sceneRect().right(),
                    m_labelContainer->rect().left(), m_labelContainer->rect().right()));
    
        pt2.setY(map(m_scene->sceneRect().top(), pt.y(), m_scene->sceneRect().bottom(),
                    m_labelContainer->rect().top(), m_labelContainer->rect().bottom()));
    
    //    qDebug() << pt << pt2 << m_scene->sceneRect() << m_labelContainer->rect();
        m_label->move(pt2.x(), pt2.y());
    
    //    m_label->setGeometry(pt.x(), pt.y(),
      //                       m_label->width(), m_label->height());
    }
    
    qreal Widget::map(const qreal & x1, qreal x, const qreal & x2, const qreal & y1, const qreal & y2)
    {
        if(x < x1)
            x = x1;
        if(x > x2)
            x = x2;
        return (x - x1) * (y2 - y1) / (x2 - x1) + y1;
    }
    
    Widget::~Widget()
    {
    
    }
    

    main.cpp

    #include "widget.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Widget w;
        w.show();
    
        return a.exec();
    }
    

    mygraphicsview.h

    #ifndef MYGRAPHICSSCENE_H
    #define MYGRAPHICSSCENE_H
    
    #include <QGraphicsScene>
    #include <QGraphicsSceneMouseEvent>
    #include <QGraphicsProxyWidget>
    #include <QGraphicsLineItem> // Added this
    
    class MyGraphicsScene : public QGraphicsScene
    {
        Q_OBJECT
    public:
        explicit MyGraphicsScene(QObject *parent = 0);
    
    signals:
        void mouseMoved(QPointF);
    public slots:
        void mouseMoveEvent(QGraphicsSceneMouseEvent * );
    private:
        QGraphicsProxyWidget * m_labelProxy;
        QGraphicsLineItem * m_lineItem; // Added this
    };
    
    #endif // MYGRAPHICSSCENE_H
    

    mygraphicsview.cpp

    #include "mygraphicsscene.h"
    #include <QDebug>
    #include <QLabel>
    #include <QVector2D>
    #include <qmath.h>
    #include <QLineF>
    
    MyGraphicsScene::MyGraphicsScene(QObject *parent) :
        QGraphicsScene(parent)
    {
        QLabel * label = new QLabel("Tracking Widget\n in Scene");
        m_labelProxy = this->addWidget(label);
    
        // added the lines below to setup an item, pointing in the positive x direction
        int x1 = 0;
        int y1 = 0;
        m_lineItem = new QGraphicsLineItem(x1, y1, x1 + 20, y1);
    //    m_lineItem->setTransformOriginPoint(x1, y1);
        this->addItem(m_lineItem);
    
        m_lineItem->setPos(-100, -100);
    }
    
    
    void MyGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent * e)
    {
    //    qDebug() << e->pos() << e->screenPos() << e->scenePos();
        emit mouseMoved(e->scenePos());
        m_labelProxy->setPos(e->scenePos());
    
        // Added these lines below to calculate and set the rotation.
        // QVector2D v;
        // v.setX(e->scenePos().x() - m_lineItem->pos().x());
        // v.setY(e->scenePos().y() - m_lineItem->pos().y());
        // m_lineItem->setRotation(qAtan2(v.y(), v.x())*180./(3.1459));
    
    
        QLineF line(m_lineItem->pos(), e->scenePos());
        m_lineItem->setRotation(360 - line.angle());
    }
    

    希望对您有所帮助。

    【讨论】:

    • phyatt,move() 函数似乎也不起作用。我在第一次创建场景时设置了MouseTracking true,但仍然没有动作。
    • 效果很好!但我正在考虑保持 qwidget 保持静止并指向光标方向。
    • 喜欢有一个指向光标的箭头吗?就像游戏中的固定炮塔将大炮对准目标?
    • 是的,我很抱歉我正在创建一个游戏,而这正是我正在做的......让大炮瞄准目标来射击它们。 ui->tankarmplay1 是坦克顶部的大炮。
    • Phyatt 非常感谢我学到了很多东西,感谢您的耐心等待。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-06
    • 2021-09-27
    • 1970-01-01
    • 1970-01-01
    • 2021-11-30
    • 2021-02-22
    • 1970-01-01
    相关资源
    最近更新 更多