如何让qlabel在场景中跟踪光标

时间:2014-02-26 02:23:44

标签: c++ qt cursor qlabel

我在场景中的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);

    }

1 个答案:

答案 0 :(得分: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在场景中移动一些文本更清晰。

widget.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());
}

希望有所帮助。