【C++】Qt组件QScrollArea的图上选点功能实现

一、基本信息

编程语言:C++
可视化平台:Qt
主要组件:QScrollArea,QLable

二、要点
1.QScrollArea

(1)用QScrollArea添加图片的代码如下:

QScrollArea scrollArea;
QLabel imageLabel;
QPixmap pixMap;
imageLabel.setPixmap(pixMap);
scrollArea.setWidget(imageLable);

(2)滚动区坐标与实际图片中坐标的转换

坐标转换公式为 QImage(X,Y)=QScroll Value(h,v)+QReal(x,y)

PImage(X,Y) 为图像的实际坐标, PScroll Value(h,v) 为水平、垂直滚动条的value()值构成的坐标, PReal(x,y) 为scrollArea的相对坐标。


这里有一个简单的例子可以解释ScrollBar的value()值和步长pageStep()之间的关系(摘自Qt Helper):
If we have a document with 100 lines, and we can only show 20 lines in a widget, we may wish to construct a scroll bar with a page step of 20, a minimum value of 0, and a maximum value of 80. This would give us a scroll bar with five “pages”.


获取QLable的相对坐标的方法可参考云鹤起舞的Qt获取鼠标位置(绝对位置、相对位置)一文

QPoint *qrealPoint;
qrealPoint= event->globalPos(); //获取全局位置,event为鼠标单击事件
qrealPoint= ui->leftImgLabel>mapFromGlobal(qrealPoint);

获取滚动条value()值的方法如下:

QScrollBar *scrollBar_X = scrollArea->horizontalScrollBar();
float x_offset = scrollBar_X->value();
2.Qt事件过滤器

此处用于实现不同QLable的单击选点事件处理,事件过滤器的主要使用方法如下:

.h文件中声明bool eventFilter(QObject *obj, QEvent *eve);
.cpp构造函数中注册ui.sa_geoImage->installEventFilter(this);
.cpp中重写eventFilter()方法

三、代码
/**
 *  @BRIEF Reimplement eventFilter()
 *  @param *obj: Which object we should control
 *  @param *eve: Which event has happened
 */
bool MatchWindowSingle::eventFilter(QObject *obj, QEvent *eve)
{
    if (obj == ui.sa_geoImage){                             //Check whether it's a geoImage Scroll Area
        if (selectPolicy == GEOIMAGE_SELECTING){            //Check whether geoImage can be selected
            if (eve->type() == QEvent::MouseButtonRelease){ //Check mouse event
                QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(eve);
                if (mouseEvent->button() == Qt::LeftButton){ // Left button click

                    //Get Image Position of the Select Point.
                    Point2f imagePoint = getImageCoordinate(mouseEvent, ui.sa_geoImage, &scaleFactor_g);                

                    //Draw point in the screen.     
                    int pointSize = (int)(2/scaleFactor_MIN_g);
                    int pix_x = (int)imagePoint.x;
                    int pix_y = (int)imagePoint.y;              
                    QPen pen(QColor(250,112,154));              //Set pen
                    QBrush brush(QColor(250,112,154));  //Set brush
                    QPainter painter(&geoPic);      
                    painter.setPen(pen);
                    painter.setBrush(brush);
                    painter.drawEllipse(QPoint(pix_x,pix_y), pointSize, pointSize);
                    painter.setRenderHint(QPainter::Antialiasing);//Make it more smooth 

                    //Update the scrollArea.
                    updateScrollArea(&geoPic, ui.sa_geoImage, &geoImageLable, &scaleFactor_g);
                    selectPolicy = VIDEOIMAGE_SELECTING;
                    return true;
                }else{return false;}
            }else{return false;}
        }else{return false;}        
    }else if (obj == ui.sa_videoImage){                     //Check whether it's a videoImage Scroll Area
        if (selectPolicy == VIDEOIMAGE_SELECTING){          //Check whether videoImage can be selected
            if (eve->type() == QEvent::MouseButtonRelease){ //Check mouse event
                QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(eve);
                if (mouseEvent->button() == Qt::LeftButton){ // Left button click

                    //Get Image Position of the Select Point.
                    Point2f imagePoint = getImageCoordinate(mouseEvent, ui.sa_videoImage, &scaleFactor_v);              

                    //Draw point in the screen.     
                    int pointSize = (int)(2/scaleFactor_MIN_v);
                    int pix_x = (int)imagePoint.x;
                    int pix_y = (int)imagePoint.y;              
                    QPen pen(QColor(254,225,64));               //Set pen
                    QBrush brush(QColor(254,225,64));   //Set brush
                    QPainter painter(&videoPic);        
                    painter.setPen(pen);
                    painter.setBrush(brush);
                    painter.drawEllipse(QPoint(pix_x,pix_y), pointSize, pointSize);
                    painter.setRenderHint(QPainter::Antialiasing);//Make it more smooth 

                    //Update the scrollArea.
                    updateScrollArea(&videoPic, ui.sa_videoImage, &videoImageLable, &scaleFactor_v);
                    selectPolicy = GEOIMAGE_SELECTING;
                    return true;
                }else{return false;}
            }else{return false;}
        }else{return false;}
    }else{return false;}
}
### 回答1: 在 Qt 界面中实现手动框选点云的步骤如下: 首先,在 Qt 的图形界面中创建一个窗口用于显示点云数据。可以使用 Qt 提供的 QGraphicsView 或 OpenGLView 控件来实现。 接下来,监听鼠标事件,例如鼠标按下、鼠标移动和鼠标释放等事件。通过 Qt 的事件过滤器或重写鼠标事件的处理函数来实现。 当鼠标按下时,记录下按下点的坐标。 当鼠标移动时,实时更新鼠标移动的位置,并用绘图工具在窗口上画出鼠标移动的路径。 当鼠标释放时,记录下释放点的坐标,并根据两个点的坐标计算出框选范围。 根据框选范围,在点云数据中计算出位于该范围内的点,并将其高亮显示或者以不同的颜色标记出来。 最后,根据项目需求决定是否需要对框选的点进行进一步操作,例如保存、导出或其他处理等。 需要注意的是,手动框选点云的实现除了需要实时更新鼠标移动的路径外,鼠标操作的精准度也是很重要的,因此可以根据项目需求对框选算法和样式进行调整和优化。 ### 回答2: 在Qt界面中实现手动框选点云的方法如下: 1. 首先,需要在Qt界面上创建一个用于显示点云的图形区域。可以使用Qt自带的QOpenGLWidget或者QGraphicsView来实现。这个图形区域将作为用户框选点云的可视化显示区域。 2. 当用户需要开始框选点云时,需要在图形区域上监听鼠标事件。通过重写鼠标事件处理函数,可以捕获鼠标在图形区域上的操作。 3. 当用户按下鼠标左键并拖动时,鼠标事件处理函数会在每一帧中不断被调用。在处理函数中,可以获取当前鼠标的坐标,并根据鼠标的移动路径,绘制一个矩形或者多边形,用于表示用户的选择区域。 4. 在进行绘制选择区域的同时,需要记录下根据当前选择区域与点云的交集,找出在选择区域内的点云数据。可以通过点云数据的坐标与选择区域的坐标进行判断,判断点云是否在选择区域内。 5. 当用户释放鼠标左键时,鼠标事件处理函数会停止被调用。此时,可以获得最终的选择区域,并再次确定选择区域内的点云数据。 6. 最后,根据得到的选择区域内的点云数据,可以进行后续的处理,如显示选中的点云,进行数据分析等。 通过以上步骤,就可以在Qt界面中实现手动框选点云的功能。这样能够更方便地进行点云数据的选择和分析,提高用户的交互体验。 ### 回答3: 在Qt界面中实现手动框选点云的方法有很多种,下面我简要介绍其中一种常用的方法。 首先,在Qt界面中创建一个显示点云的窗口,可以使用Qt自带的3D绘图功能或者调用第三方库(如PCL)来实现。在窗口中显示点云,并为点云添加事件监听器。 然后,需要实现框选功能,可以按下鼠标左键并拖动鼠标,在界面上绘制一个矩形框选区域。可以通过监听鼠标按下、按住并移动、松开鼠标的事件来实现这个功能。在鼠标按下时记录下按下的坐标,在鼠标移动时更新鼠标移动的坐标,用这两个坐标来计算出矩形的大小和位置,在鼠标松开时完成框选。 接下来,需要确定被框选的点云。通过循环遍历所有的点云,判断每个点是否在框选的区域内,可以通过比较点的坐标和框选矩形的范围来判断。符合条件的点可以被选中或者进行其他操作。 最后,根据需求对被框选的点云做出相应的处理,可以将选中的点云高亮显示、删除或者执行其他操作。 总结起来,实现Qt界面中手动框选点云的关键步骤包括创建显示点云的窗口,添加事件监听器以支持鼠标操作,实现鼠标按下、移动和松开的事件回调函数,并在其中绘制框选区域和确定被框选的点云。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值