模仿visionpro的mask功能用qt编写一个遮罩工具

616 阅读3分钟

模仿visionpro的遮罩工具,用qt写了个类似的功能,界面如下 mask.png

操作过程如下:

mask.gif

工具功能如下: 1.可控制遮罩绘制时候是起始和终止点是矩形还是圆形 2.可控制遮罩颜色,用户自定义 3.可控制遮罩线条粗细,1~150像素范围内 4.可控制遮罩当前是绘图还是移动图片模式 5.添加橡皮擦功能 6.20M以内的图绘制和移动不会卡顿

主要代码如下: mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QFileDialog>
#include "imagewidget.h"
#include "cusgraphicCaliperitem.h"
#include "cusgraphicsscene.h"
#include "cusgraphicview.h"
#include <QColorDialog>
#include "cuslabel.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void recvShowPicSignal(QImage image);
public slots:
    void slot_getColor(QColor color);
    void on_labelColor_clicked();
private slots:
    void on_pushButtonOpen_clicked();
    void on_spinBoxMaskWidth_valueChanged(int arg1);
    void on_pushButtonMoveImg_clicked();
    void on_pushButtonBrushType_clicked();
    void on_pushButtonErase_clicked();
    void on_pushButtonSaveMask_clicked();
private:
    Ui::MainWindow *ui;
    QStringList     m_strPathList;//选择图片的路径
    qint32          m_nCrtIndex;//当前图片索引
    ImageWidget     *m_Image;
    CusGraphicsScene *m_qgraphicsScene;
    CusGraphicCaliperitem * m_graphicCaliperItem;
    int             m_nBrushType;//
    bool            m_bErase;//是否使用橡皮擦
    QColorDialog    *m_pColorDialog;
    cusLabel        *labelColor;
//    myGraphicView   *mygraphicview;
};
#endif // MAINWINDOW_H

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"
//#pragma execution_character_set("utf-8")//让能够正常显示中文字符串
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
    m_Image(nullptr),
    m_graphicCaliperItem(nullptr),
    ui(new Ui::MainWindow),
    m_nBrushType(1),
    m_bErase(false),
    m_pColorDialog(nullptr),
    m_qgraphicsScene(nullptr),
    labelColor(nullptr)
{
    ui->setupUi(this);
    QFile iFile(":/ParaDlg.css");
    if (iFile.open(QFile::ReadOnly)) {
        this->setStyleSheet(iFile.readAll());
        iFile.close();
    }
//    ui->actionOpenPic->setData(1);//打开文件
//    ui->actionAddMask->setData(2);//添加遮罩
//    connect(ui->actionOpenPic,SIGNAL(triggered()), this, SLOT(onMenuEvent()));
//    connect(ui->actionAddMask,SIGNAL(triggered()), this, SLOT(onMenuEvent()));
    m_qgraphicsScene = new CusGraphicsScene;//要用QGraphicsView就必须要有QGraphicsScene搭配着用
    //mygraphicview = new CusGraphicView(this);
    ui->mygraphicview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->mygraphicview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->mygraphicview->setBackgroundBrush(QBrush(QColor(240,240,240,255)));
    QColor color = QColor(255,0,0);
    labelColor = new cusLabel(this);
    labelColor->setMinimumWidth(25);
    labelColor->setMinimumHeight(25);
    labelColor->setMaximumHeight(35);
    labelColor->setMaximumWidth(35);
    connect(labelColor,&cusLabel::mouseReleasedSig,this,&MainWindow::on_labelColor_clicked);
    ui->horizontalLayout_Color->addWidget(labelColor);
    QString strSheet ="background-color: rgb(%1, %2, %3);";
    strSheet = strSheet.arg(color.red(),0,10).arg(color.green(),0,10).arg(color.blue(),0,10);
    labelColor->setStyleSheet(strSheet);
}
MainWindow::~MainWindow()
{
    if(m_Image!=nullptr)
    {
        delete m_Image;//m_graphicCaliperItem的parentItem是m_Image,所以delete m_Image的时候也会delete m_graphicCaliperItem
        m_Image = nullptr;
    }
//    if(m_graphicCaliperItem!=nullptr)
//    {
//        delete m_graphicCaliperItem;
//        m_graphicCaliperItem =nullptr;
//    }
    if(m_qgraphicsScene!=nullptr)
    {
        m_qgraphicsScene->clear();
        delete m_qgraphicsScene;
        m_qgraphicsScene = nullptr;
    }
    delete ui;
}
void MainWindow::recvShowPicSignal(QImage image)
{
    m_qgraphicsScene->clear();
    m_Image = new ImageWidget(image);//实例化类ImageWidget的对象m_Image,该类继承自QGraphicsItem,是自己写的类
    int nwith = ui->mygraphicview->width();//获取界面控件Graphics View的宽度
    int nheight = ui->mygraphicview->height();//获取界面控件Graphics View的高度
    m_Image->setQGraphicsViewWH(nwith,nheight);//将界面控件Graphics View的width和height传进类m_Image中
    m_Image->setAcceptHoverEvents(true);
    m_qgraphicsScene->addItem(m_Image);//将1QGraphicsItem类对象放进QGraphicsScene中
    ui->mygraphicview->setSceneRect(QRectF(-(nwith/2),-(nheight/2),nwith,nheight));//使视窗的大小固定在原始大小,不会随图片的放大而放大(默认状态下图片放大的时候视窗两边会自动出现滚动条,并且视窗内的视野会变大),防止图片放大后重新缩小的时候视窗太大而不方便观察图片
    ui->mygraphicview->setScene(m_qgraphicsScene);//Sets the current scene to scene. If scene is already being viewed, this function does nothing.
    ui->mygraphicview->setFocus();//将界面的焦点设置到当前Graphics View控件
    ui->mygraphicview->setMouseTracking(true);
    ui->mygraphicview->releaseMouse();
    //添加mask的item
    if(m_graphicCaliperItem==nullptr)
    {
        m_graphicCaliperItem = new CusGraphicCaliperitem();
        m_graphicCaliperItem->setParentImgItem(m_Image);
        m_graphicCaliperItem->m_ShapeType = C_MASK;
        m_graphicCaliperItem->InitRect(QPointF(0,0),m_Image->getPicWidth(),m_Image->getPicHeight());
        m_qgraphicsScene->addItem(m_graphicCaliperItem);
    }
}
void MainWindow::on_pushButtonOpen_clicked()
{
    QFileDialog *fileDlg = new QFileDialog(this);
    fileDlg->setWindowTitle("Choose Pictures");
    QStringList qstrFilters;
    qstrFilters<<"Image files(*.bmp *.jpg *.pbm *.pgm *.png *.ppm *.xbm *.xpm)";
    qstrFilters<<"Any files (*)";
    fileDlg->setNameFilters(qstrFilters);//设置文件过滤器
    fileDlg->setFileMode(QFileDialog::ExistingFiles);//设置能选择多个文件,如果是单个文件就写成QFileDialog::ExistingFile
    if(fileDlg->exec() == QDialog::Accepted)
    {
        QStringList strPathList = fileDlg->selectedFiles();
        m_strPathList = strPathList;
        m_nCrtIndex = 0;
        QFile file(m_strPathList[m_nCrtIndex]);
        file.open(QIODevice::ReadOnly);
        QByteArray data = file.readAll();
        QImage img = QImage::fromData(data);
        recvShowPicSignal(img);
        file.close();
    }
    fileDlg->close();
    delete fileDlg;
    fileDlg = nullptr;
}
void MainWindow::on_spinBoxMaskWidth_valueChanged(int arg1)
{
    if(m_graphicCaliperItem!=nullptr)
    {
        m_graphicCaliperItem->setMaskpenWidth(ui->spinBoxMaskWidth->value());
    }
}
void MainWindow::on_pushButtonMoveImg_clicked()
{
    if(m_graphicCaliperItem!=nullptr)
    {
        //拖动、绘制
        if(ui->pushButtonMoveImg->text()=="绘制")
        {
            ui->pushButtonMoveImg->setText("拖动");
            m_graphicCaliperItem->setBackImgMovable(true);
        }
        else
        {
            ui->pushButtonMoveImg->setText("绘制");
            m_graphicCaliperItem->setBackImgMovable(false);
        }
    }
    //●■
}
void MainWindow::on_pushButtonBrushType_clicked()
{
    if(m_graphicCaliperItem!=nullptr)
    {
        if(m_nBrushType==1)
        {
            ui->pushButtonBrushType->setText("矩形");
            m_nBrushType=2;
            m_graphicCaliperItem->setBrushType(m_nBrushType);
        }
        else
        {
            ui->pushButtonBrushType->setText("圆形");
            m_nBrushType=1;
            m_graphicCaliperItem->setBrushType(m_nBrushType);
        }
    }
}
void MainWindow::on_pushButtonErase_clicked()
{
    if(m_graphicCaliperItem!=nullptr)
    {
        if(!m_bErase)
        {
            m_bErase = true;
            m_graphicCaliperItem->setErase(m_bErase);
        }
        else
        {
            m_bErase = false;
            m_graphicCaliperItem->setErase(m_bErase);
        }
    }
}
void MainWindow::on_labelColor_clicked()
{
    if(m_pColorDialog==nullptr)
    {
        m_pColorDialog = new QColorDialog(this);
        connect(m_pColorDialog,SIGNAL(colorSelected(QColor)),this,SLOT(slot_getColor(QColor)));
    }
    m_pColorDialog->exec();
}
void MainWindow::slot_getColor(QColor color)
{
    if(m_graphicCaliperItem!=nullptr)
    {
        QString strSheet ="background-color: rgb(%1, %2, %3);";
        strSheet = strSheet.arg(color.red(),0,10).arg(color.green(),0,10).arg(color.blue(),0,10);
        labelColor->setStyleSheet(strSheet);
        m_graphicCaliperItem->setMaskColor(color);
    }
}
void MainWindow::on_pushButtonSaveMask_clicked()
{
    if(m_graphicCaliperItem!=nullptr)
    {
        QBitmap bitmap = m_graphicCaliperItem->getMaskBitmap();
        QString strFileName = QFileDialog::getSaveFileName(this,tr("Save Picture"),"","PNG(*.png);;JPG(*.jpg);;BMP(*.bmp)");
        if(!strFileName.isNull())
        {
            bitmap.toImage().save(strFileName);
        }
    }
}