Qt实训项目----(3)
1.四个绘图工具功能的优化,要求:从点击第一个点开始绘图(现有的功能全部点击完成后才完成绘制);
2.添加滚轮缩放功能;
好了,第一件事还是看任务。任务1,要求对操作工具的优化,按照字面意思,就是当我们点击操作工具后然后在绘图区域点击第一个点就已经开始绘制了,证明在整个操作过程中会有一个跟随影像。比如直线吧,在你点击第一个点开始并且移动的时候,就会有一根直线的影像跟随,不管你移动到哪里总会有一条直线,路径就是点击的起点以及移动的路径。那么自然我们就能想到重写鼠标移动事件(mouseMoveEvent),还有我们需要的仅仅是移动的检测,而对于鼠标移动事件默认的是点击后在拖动。根据我们项目(2)说的,如果要设置仅仅的鼠标移动监听,那么必须要有
ui->centralWidget->setMouseTracking(true);
setMouseTracking(true);
而且我们鼠标监听的生命周期仅仅是在操作工具点击和完成之后,那么为了保险起见自然也要在函数完成的地方添加
ui->centralWidget->setMouseTracking(false);
setMouseTracking(false);
而且我们还要思考,仅仅按照我们前面设计的是有问题的,就拿直线来举例吧,我们开始定义了两个点_startPoint和_endPoint,我们没有初始化,但是按照C++语言的规则,会自动赋值为0;按照我们以前写的代码
if(_startPoint.isNull())
{
_startPoint=event->pos();
}
else
{
_endPoint=event->pos();
_drawState=0; //操作完毕,恢复初始化状态
_drawType=1;
qDebug()<<"_startPoint:"<<_startPoint;
qDebug()<<"_endPoint:"<<_endPoint;
update(); //进行重绘事件(别忘了在重绘之后对start和end初始化)
}
这样是有问题的,毕竟我们只是赋值给了开始点,那么按照我们上面说的思路当我们点击第一个起始点的时候他会直接连接到左上角(0,0)点作为一条直线。这样就是有问题的。
那么我们需要怎么做呢,只需要把_startPoint和_endPoint这两个点都赋值在第一个点就行了,那么就不会出现问题了。当然我们在需求中也知道,我们是只在这个鼠标移动事件中进行跟随影像绘制的。那么为了好分辨我们也要重新给这个事件给一个状态。
所以。。。。。。(不多说了直接上代码)
//这是槽函数改变之后的结果
void MainWindow::on_actionLine_triggered()
{
setCursor(Qt::CrossCursor);
m_Drawing = true;
_drawState=1;
}
void MainWindow::on_actionRect_triggered()
{
setCursor(Qt::CrossCursor);
m_Drawing = true;
_drawState=2;
}
void MainWindow::on_actionEllipse_triggered()
{
setCursor(Qt::CrossCursor);
m_Drawing = true;
_drawState=3;
}
void MainWindow::on_actionTriangle_triggered()
{
setCursor(Qt::CrossCursor);
m_Drawing = true;
_drawState=4;
}
看的出来我们在所有的操作工具的点击后给了一个状态m_Drawing。那么我们只需要在以前的函数体中声明这个状态就行了,证明只有在这个状态下我们才会发生这些功能。
//鼠标点击事件的修改
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
if(_drawState==0) //判断状态为初始状态(没有槽函数发生)
{
return; //返回
}
else if(_drawState==1 && m_Drawing) //直线
{
if(_startPoint.isNull())
{
ui->centralWidget->setMouseTracking(true);
setMouseTracking(true);
_startPoint = _endPoint = event->pos();
qDebug()<<"_startPoint:"<<_startPoint;
// update(); //此时起始点和终点都是一个位置,所以绘出的图形是一个点
}
else
{
_endPoint = event->pos();
qDebug()<<"_endPoint:"<<_endPoint;
_drawState=0; //操作完毕,恢复初始化状态
_drawType=1;
ui->centralWidget->setMouseTracking(false);
setMouseTracking(false);
update(); //进行重绘事件
}
}
else if(_drawState==2 && m_Drawing) //矩形
{
if(_startPoint.isNull())
{
ui->centralWidget->setMouseTracking(true);
setMouseTracking(true);
_startPoint = _endPoint = event->pos();
qDebug()<<"_startPoint:"<<_startPoint;
// update();
}
else
{
_endPoint=event->pos();
qDebug()<<"_endPoint:"<<_endPoint;
_drawState=0; //操作完毕,恢复初始化状态
_drawType=2;
ui->centralWidget->setMouseTracking(false);
setMouseTracking(false);
off_x=_endPoint.x()-_startPoint.x();
off_y=_endPoint.y()-_startPoint.y();
update(); //进行重绘事件并且对start和end进行初始化
}
}
else if(_drawState==3 && m_Drawing) //圆形
{
if(_startPoint.isNull())
{
ui->centralWidget->setMouseTracking(true);
setMouseTracking(true);
_startPoint = _endPoint = event->pos();
qDebug()<<"_startPoint:"<<_startPoint;
// update();
}
else
{
_endPoint=event->pos();
qDebug()<<"_endPoint:"<<_endPoint;
_drawState=0; //操作完毕,恢复初始化状态
_drawType=3;
ui->centralWidget->setMouseTracking(false);
setMouseTracking(false);
off_x=_endPoint.x()-_startPoint.x();
off_y=_endPoint.y()-_startPoint.y();
d=sqrt(off_x*off_x+off_y*off_y);
update(); //进行重绘事件
}
}
else if(_drawState==4 && m_Drawing) //三角形
{
if (clicked_count == 1) //clicked_count是记录我们鼠标点击的次数,即赋值给三角形的三个点
{
ui->centralWidget->setMouseTracking(true);
setMouseTracking(true);
_point1 = _point2 = _point3 = event->pos();
qDebug()<<"_point1:"<<_point1;
clicked_count = 2;
}
else if (clicked_count == 2)
{
_point2 = _point3 = event->pos();
qDebug()<<"_point2:"<<_point2;
clicked_count = 3;
}
else if (clicked_count == 3)
{
_point3 = event->pos();
qDebug()<<"_point3:"<<_point3;
clicked_count = 1;
_drawState = 0;
_drawType = 4;
ui->centralWidget->setMouseTracking(false);
setMouseTracking(false);
update();
}
}
}
//鼠标移动事件的修改
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
if (_drawState == 1 && m_Drawing)
{
_endPoint = event->pos();
_drawType = 1;
update();
}
else if (_drawState == 2 && m_Drawing)
{
_endPoint = event->pos();
_drawType = 2;
off_x=_endPoint.x()-_startPoint.x();
off_y=_endPoint.y()-_startPoint.y();
update();
}
else if (_drawState == 3 && m_Drawing)
{
_endPoint = event->pos();
_drawType = 3;
off_x=_endPoint.x()-_startPoint.x();
off_y=_endPoint.y()-_startPoint.y();
d=sqrt(off_x*off_x+off_y*off_y);
update();
}
else if (_drawState == 4 && m_Drawing)
{
if (a == 1)
{
_point2 = event->pos();
_drawType = 4;
update();
a=2;
}
else if (a == 2)
{
_point3 = event->pos();
_drawType = 4;
update();
}
}
我们重绘事件不需要修改,因为我们要的最终结果就是那样的效果,只是过程中添加了一些东西。
好了到这里我就想说任务1,已经完成了,当然我只是复制的核心代码,其余还是需要大家自己去敲(包括全局变量的定义以及声明等)。
那么看任务2,一看就知道很简单,不会太麻烦,只是单纯的增加了鼠标滑轮事件。而在我们Qt中也可以直接对鼠标滑轮事件进行重写(wheelEvent)。
在这里我要多说鼠标滑轮事件的使用
*void wheelEvent(QWheelEvent event) ----函数
在头文件中按上面形式声明 ----#include
实现文件中:
event->orientation()
event->delta()
通过调用参数对象相关的函数,获取到垂直或水平滚轮滚动,以及各自滚动的方向。(上面函数的用法需要自己去查看或者查资料我就不多说了)
代码如下:
void MainWindow::wheelEvent(QWheelEvent *event)
{
qDebug()<<QString::fromLocal8Bit("放大中心点:")<<event->pos();
if(event->delta()>0) //上滑放大
{
_factor *=1.1;
_dx=event->pos().x()*(1-_factor);
_dy=(event->pos().y()-25)*(1-_factor);
if(_factor>=10)
{
_factor=10; //保证最大放大倍数
}
update();
}
else if(event->delta()<0) //下滑缩小
{
_factor =_factor*0.9;
_dx=event->pos().x()*(1-_factor);
_dy=(event->pos().y()-30)*(1-_factor);
if(_factor<=0.2)
{
_factor=0.2; //保证缩小倍数
}
update();
}
}
这就是鼠标滑轮事件我们重写后的实现方式。
这些事件的使用,包括我们在Qt中常用的事件处理函数,我会在这几天整理出来,让大家有点印象。毕竟只有把基础做好了,才是最稳当的。很多框架用起来是挺简单听快捷的,但是很多框架都是在我们基础上整理出来的。
(在这里吐槽一下框架,框架确实挺好也挺简单便捷,但是你们可能没有遇到过,框架也会有很多坑。我们要知道,每一个开源项目包括Java JDK还有很多开源技术都是慢慢的修改,不然会有那么多版本。
所以说基础学的好,用最基础的东西多敲点代码,也许和框架实现的功能一样,但是保证至少坑少。。。嘻嘻? 有的人就会说你这是为自己不会框架找了接口吗??随便你了怎么想了。。。)