Qt对QLabel上的图像实现撤销(undo)和重做(redo)功能

tech2024-08-09  47

由于没有弄懂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从零入门教程(一):图像处理自编软件

最新回复(0)