QTextBrowser-如何从鼠标单击位置识别图像

QTextBrowser-如何从鼠标单击位置识别图像,qt,qtextdocument,qtextbrowser,Qt,Qtextdocument,Qtextbrowser,我正在使用QTextBrowser来显示包含大量图像的富文本,每个图像都用HTML标记指定,并使用QTextDocument::addResource()作为资源添加 我想能够做的是,在上下文菜单处理程序中(即使用鼠标点击位置),识别点击结束的图像。由于cursorForPosition(event->pos()).block().text()返回一个以Unicode 0xFFFC开头的字符串,因此可以判断单击是否在图像上。不幸的是,视图中的每个图像都返回相同的字符串 可以获取与QTextDoc

我正在使用
QTextBrowser
来显示包含大量图像的富文本,每个图像都用HTML
标记指定,并使用
QTextDocument::addResource()
作为资源添加

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

可以获取与
QTextDocument::allFormats()
一起使用的所有格式,确定其中哪些是图像格式,并获取它们的图像资源名称。不幸的是,似乎无法获得它们的实际显示位置或边框。

来自:

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

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

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

  • 弹出菜单应异步显示,以免阻塞应用程序的其余部分。文档中提供的示例代码是糟糕的用户体验的来源,应该被视为令人憎恶的东西。所有小部件都可以在关闭时自动删除自己,这样菜单就不会泄漏。
    QPointer
    仅用于证明这一事实。它跟踪菜单的生存期,并在菜单删除自身时将自身置空

  • #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    类浏览器:公共QTextBrowser
    {
    QPointer m_菜单;
    受保护的:
    void contextMenuEvent(QContextMenuEvent*ev){
    Q_ASSERT(m_menu.isNull());//确保菜单没有泄漏
    m_menu=createStandardContextMenu();
    qtextcursorcur=cursorForPosition(ev->pos());
    QTextCharFormat fmt=cur.charFormat();
    qDebug()setAttribute(Qt::WA_DeleteOnClose);//菜单不会泄漏
    m_menu->show();//异步显示菜单,以免阻塞应用程序
    }
    };
    无效添加图像(QTextDocument*文档、常量QString和url){
    QImage img(100100,QImage::Format_ARGB32_预乘);
    图像填充(Qt::白色);
    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[])
    {
    质量保证申请a(argc、argv);
    QTextDocument文档;
    浏览器;
    doc.setHtml(“
    ”); 添加图像和文档,”data://image1"); 添加图像和文档,”data://image2"); browser.show(); browser.setDocument(&doc); 返回a.exec(); }
    #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();
    }