QML实现的简易图文编辑器

实现一个能自由插入图片的文本编辑器。

qml的TextEdit是直接支持富文本的,可以直接插入图片,使用

<img src="" align="top,middle,bottom" width="" height="">

但是对于动图而言,解决办法之一就是手动换帧。

先上效果图:


对于简单的动图而言,自然想到使用Qt自带的QMovie进行解析。

思路是每插入一张动图,在它换帧的时候,将当前帧保存下来,并将其路径emit出去,然后在TextEdit的text中进行replace即可。

关键代码:(c++部分)

void GifHelper::addGif(QString gif)
{
    int speed = 100;  //默认为原始速度
    if (gif.left(4) == "file")
    {
        gif = gif.mid(8);
        speed = 60;     //插入的图片速度为0.6倍
    }
    QMovie *movie = new QMovie(gif, "", this);
    movie->setCacheMode(QMovie::CacheAll);
    movie->setSpeed(speed);
    connect(movie, &QMovie::finished, movie, &QMovie::start);   //循环播放
    connect(movie, &QMovie::frameChanged, this, &GifHelper::disposeFrame);
    m_gifList.append(movie);
    movie->jumpToFrame(0);  //开始前先缓存第一帧
    movie->start();
}

void GifHelper::disposeFrame(int frameNumber)
{
    QMovie *movie = qobject_cast<QMovie *>(sender());
    QString baseName = QFileInfo(movie->fileName()).baseName();
    QImage image = movie->currentImage();
    QString src = m_cachePath + baseName + "/" +
                    QString::number(frameNumber) + ".png";
    if (!QFile::exists(src))    //如果缓存图像不存在就缓存
    {
        QDir dir;
        dir.mkpath(m_cachePath + baseName + "/");
        image.save(src);
    }
    QString newData = baseName + "/" + QString::number(frameNumber) + ".png";
    QString oldData;   //前一帧
    if (frameNumber == 0)
        oldData = baseName + "/" + QString::number(movie->frameCount() - 1) + ".png";
    else oldData = baseName + "/" + QString::number(frameNumber - 1) + ".png";

    emit updateGif(oldData, newData);
}

qml部分:

TextEdit
{
    id: editor

    selectionColor: "#3399FF"
    textFormat: TextEdit.RichText   //使用富文本
    selectByMouse: true
    selectByKeyboard: true
    wrapMode: TextEdit.Wrap

    property alias cachePath: gifHelper.cachePath

    function addImage(src, w, h)
    {
        var index1 = src.lastIndexOf(".");
        var index2 = src.length;
        var suffix = src.substring(index1 + 1, index2);  //后缀名
        if (suffix === "gif" || suffix === "GIF")   //如果为动图
        {
            gifHelper.addGif(src)
            var baseName = Api.baseName(src);
            editor.insert(editor.cursorPosition, "<img src=\"file:///" +
                          gifHelper.cachePath + baseName + "/0" + ".png" +
                          "\" height=" + w + " width=" + h + ">");  //插入第一帧的图片
        }
        else  editor.insert(editor.cursorPosition,
                            "<img src=\"" + src + "\" height=" + w + " width=" + h + ">")
    }

    GifHelper
    {
        id: gifHelper

        onUpdateGif:
        {
            var pos = editor.cursorPosition;
            var selstart = editor.selectionStart;
            var selend = editor.selectionEnd;
            editor.text = editor.text.replace(oldData, newData);    //手动换帧
            editor.cursorPosition = pos;
            editor.select(selstart, selend);
        }
    }
}
总结:表面上看感觉还勉强可以,实际上动图过多时有严重的性能问题。Qt自带的例子有一个使用QTextObject的,然鹅qml目前好像没有找到相关的东东,唯一有关的就是TextEdit里的 textDocument : TextDocument,但是并不知道怎么用,以后学会了再写相关的。

猜你喜欢

转载自blog.csdn.net/u011283226/article/details/79223145