天天看点

Qt获取鼠标位置(绝对位置、相对位置)

在进行界面编程时,经常需要获取鼠标的位置,特别是需要知道鼠标在界面上某个控件的相对位置。在Qt其实获取这几种位置还是比较简单的。首先我们需要了解Qt的坐标系统,Qt的坐标系统是有QPainter类控制的,而QPainter是在绘图设备上绘制。而有时我们并不需要进行绘图只需要通过鼠标事件获取坐标位置而已,这时我们需要了解两点:坐标系统和控件的层次关系。首先默认坐标系统中原点(0,0)在其左上角,x坐标向右增长,y坐标向下增长。在基于像素的设备上,默认的单位是一个像素,而在打印机上默认的单位是一个点(1/72英寸)。控件的层次关系是根据控件在界面中的布局位置决定的,如下:leftImgLabel的位置就相对于centralWidget而言,通过leftImgLabel.pos()获取的位置并不是全局位置而是相对于centralWidget的位置。

Qt获取鼠标位置(绝对位置、相对位置)

如果通过leftImgLabel来显示图片,通过鼠标来获取图片中某个点的位置,如果直接使用鼠标事件中的event->pos()获取的位置并不对应你实际标注的图像上的点,而是鼠标相对于当前窗口的位置(event->globalPos()获取的鼠标相对于当前显示器的位置,可以采用任意截图工具进行测试)。这时就需要将鼠标坐标根据控件的层次关系去转换。

Qt获取鼠标位置(绝对位置、相对位置)

上图中红色方框右下角的坐标:event->pos():QPoint(269,287),event->globalPos: QPoint(763,549)而真实对应的图片中的坐标则是pos()-(centralWidget.pos()+leftImgLabel.pos())(窗口坐标减去父窗口坐标和当前窗口坐标).

其实在Qt中有比较简单的方式去获取QLabel上内容的坐标:

leftButtomRightPoint = event->globalPos();                          //获取全局位置      
leftButtomRightPoint = ui->leftImgLabel->mapFromGlobal(leftButtomRightPoint);      

首先鼠标获取全局坐标,然后通过QLabel封装的mapFromGlobal函数进行转换。 注意这时获取的坐标都还只是QLabel中的位置(相对于QLabel的坐标原点而言)!但是由于QLabel的具体范围和QLbael上显示的内容位置并不一致,如果QLabel显示的图片如下:

Qt获取鼠标位置(绝对位置、相对位置)

此时图片并没有填充满整个QLabel的空间,只是占用其中一部分内容,这时就需要知道图像在QLabel中的具体位置了。当图像不能填充满整个QLabel空间时,需要在QLabel的显示属性设置对齐方式,这时推荐采用居中对齐(方便后续处理,其他对齐方式计算可能不方便)

设置QLabel的对齐方式采用:

ui->leftImgLabel->setAlignment(Qt::AlignCenter);		//居中显示      

设置好显示方式后,就可以知道图像在QLabel中的位置啦(正中间),然后就可以计算图像相对于QLabel的偏移量啦,计算方式如下:

//QLabel内容相对于QLbael本身的偏移量      
xoffset = (ui->leftImgLabel->contentsRect().width()-ui->leftImgLabel->pixmap()->rect().width())/2;      
yoffset = (ui->leftImgLabel->contentsRect().height()-ui->leftImgLabel->pixmap()->rect().height())/2;      

contentsRect表示的是QLabel的内容范围,而pixmap->rect()则表示的图像的实际大小,通过这样的处理就可以得出图像相对于QLabel的具体偏移量,然后这时就可以真正将鼠标坐标转换成图像上的点位置了:

topPoint.x = leftTopLeftPoint.x()-xoffset;      
topPoint.y = leftTopLeftPoint.y()-yoffset;      
buttomPoint.x = leftButtomRightPoint.x()-xoffset;      
buttomPoint.y = leftButtomRightPoint.y()-yoffset;      

通过这样的转换终于可以将鼠标选取的点转为我们想要的坐标(相对坐标).

总结:

1.注意控件的层次关系

2.注意填充内容相对于控件本身的位移