使用 QTextEdit 中的链接

问题描述 投票:0回答:1

全部,

如果我有一个带有一堆文本的 QTextEdit,并且想要在该文本中的某个位置插入一个超链接,我是否可以免费处理该超链接,或者我将不得不编写一些额外的代码来处理超链接悬停/单击?

蒂亚!

[编辑]

我的意思是问 - 输入 www.google.com 并按

Space Bar
Enter
键后 QTextEdit 是否可以识别超链接,以便正确呈现。 我不希望我的用户输入
< a href=....

谢谢您,对于造成的混乱深表歉意。

[/编辑]

qt hyperlink qtextedit
1个回答
0
投票

迟到的答复总比没有答复好。我已经解决了这个问题,以回答用户@caramel的另一个问题,不幸的是,在我完成之前,他已经删除了它......我想我最好不要让它浪费掉。

QTextEdit
中显示链接很简单:使用 QTextBrowser 子类。这是有关该主题的许多问题中给出的答案;然而,所有这些问题都仅限于使链接在小部件中正确运行,并且没有一个真正解决用户可以键入 URL 的情况。

有许多细节需要解决,所有这些都使得练习变得非常重要:

  • 检测到正在输入 URL
  • 解决 URL 被删除的情况
  • 确保按空格/Enter 编辑下一个单词时链接不会扩展。

识别网址

这个答案中呈现的模式是我选择在这里使用的模式。 它需要一些小的修复才能在 C++ 中工作(所有

\
必须为编译器转换为
\\
)并在编辑期间工作(该模式必须被元素包围以保证它不会与粘在没有空格来分隔它们的单词。

(\\(|\\b)https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)(\\)|\\b)

解决方案

由于其

QTextBrowser

 方法,
setOpenExternalLinks
仍然是首选类别。如果没有这个,您最好的办法就是复制 URL 粘贴到浏览器中,而不是直接单击生成的链接。
话虽如此,
QTextBrowser
默认情况下是只读的,我们需要解决这个问题。

为了避免读取控件包含的整个文本,我们使用

QTextCursor
来确定当前正在编辑的文本部分。
因为我们要改变它(要创建链接,我们必须用 markdown
linkAddress
替换正在键入的
[linkAddress](linkAddress)
文本),所以我们需要在方法末尾恢复光标位置。

这是一个完整的解决方案,所有逻辑都在连接到

QTextEdit::textChanged
的 lambda 中设置。

#include <QtWidgets/QApplication>
#include <QtCore/QRegularExpression>
#include <QtWidgets/QTextBrowser>
#include <QtGui/QTextDocumentFragment>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);


    QTextBrowser* te = new QTextBrowser();
    te->setReadOnly(false);
    te->setOpenExternalLinks(true);
    te->setTextInteractionFlags(Qt::TextEditorInteraction | Qt::TextBrowserInteraction);
    //MySyntaxHighlighter* highlighter = new MySyntaxHighlighter(te);
    QRegularExpression re(
        "(\\(|\\b)https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)(\\)|\\b)",
        QRegularExpression::PatternOption::CaseInsensitiveOption | QRegularExpression::PatternOption::DontCaptureOption | QRegularExpression::PatternOption::InvertedGreedinessOption
    );

    QObject::connect(te, &QTextEdit::textChanged, [te, re]() {
        auto cursor = te->textCursor();
        int cachedPosition = cursor.position();
        auto testSeparator = [](char16_t character) -> bool {
            return character == ' ' || character == '\r' || character == '\n' || character == '\t' ||
                character == 8233 /*\u2029: paragraph separator*/
                ;
        };

        //Browse the text around where the edition is taking place
        char16_t character = '\0';
        if (!cursor.atStart()) {
            do {
                if (!cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor))
                    break;
                character = cursor.selectedText()[0].unicode();
            } while (!testSeparator(character));

            cursor.clearSelection();
            if (testSeparator(character))
                cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor);
        }

        do {
            if (!cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor))
                break;
            character = cursor.selectedText().right(1)[0].unicode();
        } while (!testSeparator(character));


        //Change the text to create/remove a link if necessary
        if (auto textToAnalyze = cursor.selectedText(); re.match(textToAnalyze).hasMatch()) { //Add link if a URL is detected
            te->blockSignals(true);
            cursor.beginEditBlock();
            cursor.removeSelectedText();
            cursor.insertMarkdown(QStringLiteral("[%1](%1)").arg(textToAnalyze));
            cursor.endEditBlock();
            te->blockSignals(false);
        }
        else if (auto textMarkDown = cursor.selection().toMarkdown(); re.match(textMarkDown).hasMatch()) { //Remove link if a URL is being removed (Del / backspace key)
            te->blockSignals(true);
            cursor.beginEditBlock();
            cursor.removeSelectedText();
            if (!textToAnalyze.isEmpty())
                cursor.insertMarkdown(textToAnalyze);
            cursor.endEditBlock();
            te->blockSignals(false);
        }
        else
            return;
        cursor.setPosition(cachedPosition);
        te->setTextCursor(cursor);
        });
    te->show();

    return a.exec();
}
© www.soinside.com 2019 - 2024. All rights reserved.