Qt随记-鼠标十字丝辅助线,QGraphicsView和Scene的SetSceneRect

1.缩放View时最好使用Matrix进行控制。在继承QGraphicsView时添加以下内容:

QWGraphicsView::QWGraphicsView(QWidget *parent):QGraphicsView(parent)  //这里改动(QWidget *parent):QGraphicsView(parent)
{

    //this->setMouseTracking(true);
//    m_img_scene_ptr = new ShowGraphicsScene();
//    this->setScene(m_img_scene_ptr);

    double width_scale = double(this->width()) / double(640);
    double height_scale = double(this->height()) / double(360);
    m_zoom_factor = width_scale < height_scale ? width_scale : height_scale;
    //m_zoom_factor = 1;
    this->updateScene();

}
void QWGraphicsView::wheelEvent(QWheelEvent *event)
{
    if (event->delta() > 0 && m_zoom_factor < 3)
    {
        m_zoom_factor *= 1.15;
    }
    else if(event->delta() <= 0 && m_zoom_factor > 0.1)
    {
        m_zoom_factor *= 0.9;
    }

    this->updateScene();

}
void QWGraphicsView::updateScene()
{
    QMatrix matrix;
    matrix.scale(m_zoom_factor, m_zoom_factor);
    this->setMatrix(matrix);
}

相应头文件中添加:

 double m_zoom_factor;
 void wheelEvent(QWheelEvent *event);
 void updateScene();

2.在场景中加入鼠标十字跟随丝辅助线时,出现了两个问题:一个是报错,item's scene (xxx) is different from scene(xxx). 一个是鼠标在进入场景的时候是作为两个LineItem加入的场景,View会默认进行视口扩展,导致加入的图片出现移动。 

第二个问题在博客https://blog.csdn.net/wingover/article/details/88036106 有介绍,只要用View的SetSceneRect函数设置View的视口即可,就不会因为Qt的默认设置导致场景Item的移动。

第一个问题找了好久最后发现是因为在Scene->clear()时会给scene重新分配地址,而我在scene中添加的十字丝(LineItem)是add进前一个场景scene的,这就导致removeItem的时候报scene场景不同的错误。

解决办法就是 在scene->clear()时分配Item的地址,再进行十字丝的add操作。

代码参考:

首先在Scene场景改变时的代码部分(我这里是在切换scene中显示的图片时)

    if(xLineOldAdress!=nullptr ) //十字丝横向线,QGraphicsLineItem类型,定义于头文件
    {
        delete xLineOldAdress;
        xLineOldAdress = nullptr;
    }
    if( yLineOldAdress != nullptr) //十字丝纵向线
    {
        delete yLineOldAdress;
        yLineOldAdress = nullptr;
    }

    xLineOldAdress = new QGraphicsLineItem;
    yLineOldAdress = new QGraphicsLineItem;

    LineCur = false;  //是否显示十字丝(在无图片载入的时候不现实)


    SceneImg->clear();
    SceneImg->addPixmap(pix);//加入影像
    ui->ViewPicture->setSceneRect(0,0,w,h); //设置视口,避免触发View视口改变的默认设置
    ui->ViewPicture->setScene(SceneImg); //显示场景

然后在鼠标移动的槽函数中添加以下代码:

    if(xLineOldAdress && LineCur)//xLineOldAdress 记录前一位置十字丝
    {
        SceneImg->removeItem(xLineOldAdress);
        SceneImg->update();

    }
    if(yLineOldAdress && LineCur) //yLineOldAdress
    {
        SceneImg->removeItem(yLineOldAdress);
        SceneImg->update();
    }

    if(xLineOldAdress!=nullptr) //启用十字丝以后在场景中添加十字丝
    {
        xLineOldAdress->setLine(pointScene.x()-2000,pointScene.y(),pointScene.x()+2000,pointScene.y());
        SceneImg->addItem(xLineOldAdress);
        LineCur = true;
    }

    if(yLineOldAdress!=nullptr)
    {
        yLineOldAdress->setLine(pointScene.x(),pointScene.y()-2000,pointScene.x(),pointScene.y()+2000);
        SceneImg->addItem(yLineOldAdress);
        LineCur = true;

    }

十字丝效果如图:

鼠标因为截图工具的原因没有显示出来,实际上是用

ui->ViewPicture->setCursor(Qt::CrossCursor);

设置为十字丝形式,十字丝会跟随鼠标移动并不会增加内存的消耗。

 

3.在设计十字丝的时候想着使用Qt的paintEvent事件进行绘制,最后还是作罢,因为需要在图片上进行绘图。使用PaintEvent显然没有scene机制方便。

这里记录一下在View中使用PaintEvent,以备不时之需。同样也是实现十字丝跟踪。

在继承QGraphicsView中添加paintEvent函数

void MyGraphicsView::paintEvent(QPaintEvent *)
{
    QPainter painter(this->viewport());
    QPen pen;
    pen.setWidth(5);
    pen.setColor(Qt::red);
    painter.setPen(pen);
    //绘制横向线
    painter.drawLine(0, lasPos.y(), width(), lasPos.y());
    //绘制纵向线
    painter.drawLine(lasPos.x(), 0, lasPos.x(), height());
}

在同时添加mouseMoveEvent函数

void MyGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
    //鼠标移动事件
    lasPos = event->pos();  //在头文件中声明QPoint lasPos
    viewport()->update();
    QGraphicsView::mouseMoveEvent(event);
}

记得在构造函数中设置鼠标可跟踪

this->setMouseTracking(true);

 

效果:

没有研究如何在这里面加入背景图片进行绘制。感觉还是scene方便。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值