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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值