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方便。