由于没有弄懂Qt官方的QUndoStack、QUndoCommand功能,网上资料也比较少,所以没有实现撤销和重做的功能,因此通过其他办法实现。
思路:设置一个C++标准容器Vector用来存放,QLabel上的图像每更新一次,即为显示一次图像(执行一次showimage命令),便会往Vector存放一次数据,待到执行撤销和重做的操作时,再对Vector进行访问。
mainwindow.h
public:
// 存储图像的Vector容器
std::vector<std::vector<QImage> > img_Vector;
// Vector迭代器
std::vector<QImage>::iterator iter;
//在容器内初始化一张图像,以及其他初始数据
void init_image();
private slots:
//QLabel显示图像
void showimage(QImage Img,bool flag);
// 撤销
void undo();
// 重做
void redo();
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
//初始容器大小
imgVector.resize(2);
//调用初始化函数
init_image();
//撤销和重做的命令实现
connect(ui->actionundo,SIGNAL(triggered()),this,SLOT(undo()));
connect(ui->actionredo,SIGNAL(triggered()),this,SLOT(redo()));
}
初始化图像
void MainWindow::init_image()
{
//初始化一张500×500的空白图像
QImage image = QImage(500, 500, QImage::Format_RGB32);
image.fill(qRgb(255, 255, 255));
ui->label->setPixmap(QPixmap::fromImage(image));
//插入vector容器
imgVector[0].push_back(image);
// 最后一个元素对应的迭代器指针
iter = imgVector[0].end() - 1;
// 初始状态下不允许撤销
ui->actionundo->setEnabled(false);
// 结束状态下不允许重做
ui->actionredo->setEnabled(false);
};
QLabel显示图像
void MainWindow::showimage(QImage Img,bool flag)
{
ui->label->setPixmap(QPixmap::fromImage(Img));
ui->label->resize(Img.width(), Img.height());
if (flag == true)
{
if (iter != (imgVector[0].end() - 1))
{
imgVector[0].erase(++iter, imgVector[0].end());
}
imgVector[0].push_back(Img);
iter = imgVector[0].end() - 1;
ui->actionundo->setEnabled(true);
ui->actionredo->setEnabled(false);
}
};
扩大图像(测试使用)
void MainWindow::enlarge_image()
{
QImage src=ui->label->pixmap()->toImage();
//QImage--->Mat格式转换
Mat img=OpenCVtoQt::QImageToCvMat(src);
//对Mat格式的图像文件进行各种图像处理操作,如灰度处理,二值化等
Mat dst;
cv::resize(img,dst,Size(),1.1,1.1);
//Mat格式的图像转化为QPixmap格式
QImage temp=OpenCVtoQt::cvMatToQImage(dst);
//显示在QLabel_2上
//ui->label_2->setPixmap(temp);
showimage(temp,true);
};
撤回和重做
// 撤销
void MainWindow::undo()
{ // 前面还有对象
if (iter != imgVector[0].begin())
{
iter--;
//qDebug()<<*iter;
showimage(*iter, false);
ui->actionredo->setEnabled(true);
// 判断自减后是否为初始图像
if (iter == imgVector[0].begin())
{
//撤销到最开始一步,按钮不可点击
ui->actionundo->setEnabled(false);
}
}
}
// 重做
void MainWindow::redo()
{ // 后面还有对象
if (iter != (imgVector[0].end() - 1))
{
iter++;
showimage(*iter, false);
ui->actionundo->setEnabled(true);
if (iter == (imgVector[0].end() - 1))
{
//重做到最后一步时,按钮不可点击
ui->actionredo->setEnabled(false);
}
}
}
参考文献:
【QT】QT从零入门教程(一):图像处理自编软件