4

我正在使用 aQTextBrowser来显示包含许多图像的富文本,每个图像都使用 HTML<img>标记指定并使用QTextDocument::addResource().

我想做的是,在上下文菜单处理程序中(即鼠标单击位置可用),识别单击结束的图像。可以判断点击是否在图像上,因为cursorForPosition(event->pos()).block().text()返回一个以 Unicode 0xFFFC 开头的字符串。不幸的是,视图中的每个图像都返回相同的字符串。

可以获取所有使用的格式QTextDocument::allFormats(),识别其中哪些是图像格式,并获取它们的图像资源名称。不幸的是,似乎没有办法获得它们的实际显示位置或边界矩形。

4

1 回答 1

2

文档中:

内联图像由具有关联 QTextImageFormat 的对象替换字符(Unicode 中的 0xFFFC)表示。图像格式使用 setName() 指定用于定位图像的名称。

您可以使用charFormat().toImageFormat().name()光标来提取图像的 URL。下面是一个独立的例子。有两个值得注意的细节:

  1. 光标有时会指向图像前面的一个字符。因此解决方法;Qt 4.8.5 和 5.1.1 似乎都有必要。

  2. 弹出菜单应异步显示,以免阻塞应用程序的其余部分。文档中提供的示例代码是不良用户体验的根源,应该被视为邪恶的可憎之物。所有小部件在关闭时都可以自动删除,因此菜单不会泄漏。AQPointer仅用于证明这一事实。它跟踪菜单的生命周期,并在菜单删除自身时将自身归零。

#include <QApplication>
#include <QTextBrowser>
#include <QImage>
#include <QPainter>
#include <QMenu>
#include <QContextMenuEvent>
#include <QTextBlock>
#include <QPointer>
#include <QDebug>

class Browser : public QTextBrowser
{
    QPointer<QMenu> m_menu;
protected:
    void contextMenuEvent(QContextMenuEvent *ev) {
        Q_ASSERT(m_menu.isNull()); // make sure the menus aren't leaking
        m_menu = createStandardContextMenu();
        QTextCursor cur = cursorForPosition(ev->pos());
        QTextCharFormat fmt = cur.charFormat();
        qDebug() << "position in block" << cur.positionInBlock()
                 << "object type" << cur.charFormat().objectType();
        if (fmt.objectType() == QTextFormat::NoObject) {
            // workaround, sometimes the cursor will point one object to the left of the image
            cur.movePosition(QTextCursor::NextCharacter);
            fmt = cur.charFormat();
        }
        if (fmt.isImageFormat()) {
            QTextImageFormat ifmt = fmt.toImageFormat();
            m_menu->addAction(QString("Image URL: %1").arg(ifmt.name()));
        }
        m_menu->move(ev->globalPos());
        m_menu->setAttribute(Qt::WA_DeleteOnClose); // the menu won't leak
        m_menu->show(); // show the menu asynchronously so as not to block the application
    }
};

void addImage(QTextDocument * doc, const QString & url) {
    QImage img(100, 100, QImage::Format_ARGB32_Premultiplied);
    img.fill(Qt::white);
    QPainter p(&img);
    p.drawRect(0, 0, 99, 99);
    p.drawText(img.rect(), url);
    doc->addResource(QTextDocument::ImageResource, QUrl(url), img);
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QTextDocument doc;
    Browser browser;
    doc.setHtml("<img src=\"data://image1\"/><br/><img src=\"data://image2\"/>");
    addImage(&doc, "data://image1");
    addImage(&doc, "data://image2");
    browser.show();
    browser.setDocument(&doc);
    return a.exec();
}
于 2013-09-19T17:40:33.623 回答