qt项目-《图像标注软件》源码阅读笔记-CentralWidget类及其子类

发布时间:2023年12月25日

目录

1. CentralWidget 概览??

2.?CentralWidget 基类

3.?CentralWInit2D

3.1 源码


?

1. CentralWidget 概览??

功能:CentralWidget 负责主窗口中心组件的界面初始化以及后续中心组件的管理。

其两个派生类分别负责2D、3D中心组件,2d和3d的模式可以进行切换。

子类CentralWInit2D方法都是实现父类方法。CentralWInit3D有一些自己的方法。

  • 内部的绘画以及标注相关的动作交由Label类(或Label3D类)进行处理;
  • 命令的撤销和重做交由Command2D类(或Command3D)进行处理;
  • 标注文件的解析和存储,以及3D图片系列文件的解析均交由Parse类进行处理。
    ?

2.?CentralWidget 基类

都是虚函数。

#ifndef CENTRALWIDGET_H
#define CENTRALWIDGET_H

#include<QMainWindow>
#include<QWidget>
#include<QListWidgetItem>
#include"Namespace.h"

/// \brief 中心组件基类
class My::CentralWidget:public QWidget{
    Q_OBJECT

public:
signals:

    /// \brief 标注选中状态改变信号
    void selectedChanged(int index,bool b);

    /// \brief 标注删除信号
    void labelDeleted(int index);

    /// \brief 标注解析完毕信号
    void labelsFinished(QList<My::Shape*>& shapes);

    /// \brief 标注添加信号
    void labelAdded(My::Shape* shape,int index);

    /// \brief 标注改变信号
    void labelChanged(int index,My::Shape* shape);

public:

    CentralWidget(QWidget* parent):QWidget(parent){}


    /// \brief 用来初始化中心组件
    virtual void setUp(QMainWindow* w);

    /// \brief 解析文件(显示图片,解析标注形状)
    virtual void parse(const QString& fileName,const QString& labelfileName);//解析标注文件

    /// \brief 改变标注的状态,槽函数
    virtual void changeShapeLabel(QListWidgetItem* item);

    /// \brief 改变标注的选中状态、槽函数
    virtual void changeSelected();

    /// \brief 创建标注形状
    virtual void createShape(My::shapeStatus s);

    /// \brief 处理按键事件
    virtual void keyPressHandle(int k);

    /// \brief 编辑标注
    virtual void editLabel();

    /// \brief 删除标注
    virtual void deleteLabel();

    /// \brief 编辑画刷大小,画刷是用来进行分割标注
    virtual void editBrush();

    /// \brief 编辑标注形状的颜色
    virtual void editColor();

    /// \brief 放大功能
    virtual void zoomIn();

    /// \brief 缩小功能
    virtual void zoomOut();

    /// \brief 使中心组件宽度适应主窗口
    virtual void fitWindow();

    /// \brief 恢复图片原始大小
    virtual void originalSize();

    /// \brief 放大镜功能
    virtual void magnifier(bool b);

    /// \brief 保存文件功能
    virtual void save(const QString& fileName);

    /// \brief 隐藏标注
    virtual void hidePolygons();

    /// \brief 显示标注
    virtual void showPolygons();

    /// \brief 关闭文件功能
    virtual void closeFile();
    virtual ~CentralWidget()=0;
};

#endif // CENTRALWIDGET_H

3.?CentralWInit2D

该子类就是实现父类方法。

#ifndef CENTRALWINIT2D_H
#define CENTRALWINIT2D_H

#include<QScrollArea>
#include<QListWidgetItem>
#include"Shape2D.h"
#include"CentralWidget.h"

/// \brief 2d中心组件,继承CentralWidget
///
/// 内部的绘画以及标注相关的动作交由Label类
/// 命令的撤销和重做交由Command2D类
/// 标注文件的解析和存储交由Parse类进行处理
class CentralWInit2D:public My::CentralWidget{
    Q_OBJECT

private:

    /// \brief 2d中心组件滚动区域
    QScrollArea* sarea;

public:
    
    /// \brief 命令栈用来存放所用到的所有标注形状
    QList<My::Shape2D*> trashshapes;
    
    /// \brief 中心绘制组件,用来展示图片、绘制标注
    My::Label* label;

    /// \brief 命令栈组件,用来实现撤销、重做命令
    My::Command2D* command;

    /// \brief 构造函数
    CentralWInit2D(QWidget* parent);

    /// \brief 用来初始化中心组件
    virtual void setUp(QMainWindow* w);

    /// \brief 解析文件(显示图片,解析标注形状)
    virtual void parse(const QString& fileName,const QString& labelfileName);/// \brief 解析标注文件

    /// \brief 改变标注的状态,槽函数
    virtual void changeShapeLabel(QListWidgetItem* item);

    /// \brief 改变标注的选中状态、槽函数
    virtual void changeSelected();

    /// \brief 创建标注形状
    virtual void createShape(My::shapeStatus s);

    /// \brief 处理按键事件
    virtual void keyPressHandle(int k);

    /// \brief 编辑标注
    virtual void editLabel();

    /// \brief 删除标注
    virtual void deleteLabel();

    /// \brief 编辑画刷大小,画刷是用来进行分割标注
    virtual void editBrush();

    /// \brief 编辑标注形状的颜色
    virtual void editColor();

    /// \brief 放大功能
    virtual void zoomIn();

    /// \brief 缩小功能
    virtual void zoomOut();

    /// \brief 使中心组件宽度适应主窗口
    virtual void fitWindow();

    /// \brief 恢复图片原始大小
    virtual void originalSize();

    /// \brief 放大镜功能
    virtual void magnifier(bool b);

    /// \brief 保存文件功能
    virtual void save(const QString& fileName);

    /// \brief 隐藏标注
    virtual void hidePolygons();

    /// \brief 显示标注
    virtual void showPolygons();

    /// \brief 关闭当前文件
    void closeFile();
    ~CentralWInit2D();
};

#endif // CENTRALWINIT_H

3.1 源码

新建command, sarea, label三个对象?;三者关系

/// \brief 2d中心组件构造函数
CentralWInit2D::CentralWInit2D(QWidget* w):My::CentralWidget (w){
    
    //初始化command
    command=new My::Command2D();
    command->manager=this;
    
    //初始化中心滚动区域
    sarea=new QScrollArea();
    
    //初始化label
    label=new My::Label(sarea);
    label->manager=this;
}

/// \brief 2d中心组件初始化函数
void CentralWInit2D::setUp(QMainWindow *w){
    w->setCentralWidget(sarea);  // 将中心滚动区域 设置为主窗口 w 的中心组件。
    sarea->setWidget(label);     // 将标签(label)设置为滚动区域(sarea)的组件。
    sarea->setAlignment(Qt::AlignCenter);
}

?载入标注文件

/// \brief 2d中心组件的解析函数
///
/// 在2d模式下,有文件读入时,会调用解析函数,初始化label中的图片以及标注等信息
void CentralWInit2D::parse(const QString &fileName,const QString &labelfileName){
    label->status=My::NoShape;//初始为noshape状态
    label->current=-1;//当前标注初始为-1,即不存在
    
    //加载图片
    label->pixmap->load(fileName);
    
    //调用Parse的静态解析函数,初始化标注形状
    My::Parse::parse(fileName,label->shapes,labelfileName);
    
    //清空trashshape
    trashshapes.clear();  // 存放删除的shape垃圾站

    //更新label
    label->update();
      
    //发送解析完毕信号,初始化标签列表
    QList<My::Shape*> temp;
    for(int i=0;i<label->shapes.length();i++){
        temp.push_back(label->shapes[i]);
    }


    emit labelsFinished(temp);
}

标签列表:

/// \brief 改变标注状态
///
/// 当标签列表中的item发生改变时,便会调用该槽函数
void CentralWInit2D::changeShapeLabel(QListWidgetItem *item){
    
    //获得标签列表组件
    QListWidget* lw=item->listWidget();
    
    //定位改变item的位置  获取当前item在标签列表中的位置(行号)。
    int index=lw->row(item);
    
    //同步item的状态,如被隐藏,以及标注文字被改变等
    label->shapes[index]->isHide=!(item->checkState());
    label->shapes[index]->label=item->text();
    
    //更新
    label->update();
}

/// \brief 改变当前被选中的标注
///
/// 当标签列表中选中发生改变时,会调用该槽函数
void CentralWInit2D::changeSelected(){
    
    //获取标签列表组件
    QListWidget* lw=qobject_cast<QListWidget*>(sender()); // 获取发送信号的对象,即标签列表组件。
    int temp=lw->count();
    
    //同步选中状态,若被选中,则改变形状的填充状态为被选中,同时改变当前标注值即current。若不被选中,则反之
    for(int index=0;index<lw->count();index++){
        if(lw->item(index)->isSelected()){
            label->shapes[index]->isFill=true;
            temp=index;
        }
        else label->shapes[index]->isFill=false;
    }
    
    //若无被选中的标注,则更新current为-1;反之则为被选中的序号
    if(temp==lw->count())label->current=-1;
    else label->current=temp;
    
    //改变current的同时,发出信号,使mainwindow改变为Focus状态,该状态下可对标注进行相应的更改
    if(label->current!=-1)emit selectedChanged(label->current,true);
    
    //更新
    label->update();

}
/// \brief 创建标注形状
///
/// 当触发创建各种形状时,会经过mainwindow调用该函数
void CentralWInit2D::createShape(My::shapeStatus s){
    
    //若是在创建形状的状态下改变创建的形状类型,若之前有未创建完的标注,则删掉
    if(label->status==My::BrushShape || label->status==My::RectangleShape || label->status==My::PolygonsShape || label->status==My::CircleShape){
        if(label->current!=-1){
            label->shapes.pop_back();
            label->current=-1;
        }
    }
    
    //同步更改label的状态
    label->status=s;  //{BrushShape,...,CurveShape,NoShape,InShape};
    
    //如果之前是选中状态即Focus状态,则发射信号,使mainwindow进入创建状态
    if(label->current!=-1)emit(selectedChanged(label->current,false));

    //更改current为-1;
    label->current=-1;
}

?回车键和esc键

/// \brief 处理创建标注过程中的按键事件
///
/// 当是回车键和esc键时,mainwindow会将事件转发到这里来进行处理
void CentralWInit2D::keyPressHandle(int k){
    
    if(k==Qt::Key_Enter || k==Qt::Key_Return){  // 多边形时,按回车结束标注。
        
        //如果是创建形状状态
        if(label->status==My::PolygonsShape || label->status==My::BrushShape || label->status==My::CurveShape){
            if(label->current==-1)return;
            
            //如果当前已创建标注形状
            bool isOk;
            
            //提醒用户键入标注文字
            QString text=QInputDialog::getText(this,"label me!","Please input the label",QLineEdit::Normal,"",&isOk);
            
            if(isOk){
                
                //添加标注,同时发射信号,使标签列表组件同步的增加标注
                label->shapes[label->current]->label=text;
                emit(labelAdded(label->shapes[label->current],label->current));
                command->logAdd(label->current);
                
                //更改current为-1
                label->current=-1;
                return;
            }
        }
        return;
    }
    if(k==Qt::Key_Escape){
        
        //如果是在创建形状过程中
        if(label->status==My::PolygonsShape || label->status==My::CircleShape || label->status==My::RectangleShape || label->status==My::BrushShape || label->status==My::CurveShape){
            if(label->current==-1)return;
            
            //如果之前有创建的形状,则删掉
            else{
                label->shapes.removeLast();
                label->current=-1;
                label->update();
            }
        }
        return;
    }
}

?

待续。。。


参考:GitHub - jameslahm/labelme: A image annotation software for 2D or 3D images

文章来源:https://blog.csdn.net/jizhidexiaoming/article/details/135170682
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。