模仿visionpro的遮罩工具,用qt写了个类似的功能,界面如下
操作过程如下:
工具功能如下: 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);
}
}
}