16

I want to use QTextEdit (in read-only mode) to show a clickable hyperlink, I used to do

QTextEdit *textEdit = new QTextEdit;
QTextCursor cursor(textEdit->document());
textEdit->setTextCursor(cursor);
cursor->insertHtml("<a href=\"www.google.com\" >Google</a>");
textEdit->show();

this code will show Google as hyperlink but unable to click.
And if I used

QTextEdit *textEdit = new QTextEdit;
QTextCursor cursor(textEdit->document());
textEdit->setTextCursor(cursor);
QTextCharFormat linkFormat = cursor.charFormat();
linkFormat.setAnchor(true);
linkFormat.setAnchorHref("http://www.google.com");
linkFormat.setAnchorName("Google");
cursor.insertText("Google", linkFormat);

then nothing happen. "Google" is just normal text.

Please help me insert clickable hyperlink to QTextEdit.

6 Answers 6

15

To have clickable hyperlink in QTextEdit, you can use

  1. QTextCharFormat::setAnchorHref to set the link for some text

  2. QWidget::mousePressEvent to capture mouse press event

  3. QTextEdit::anchorAt to obtain the link

Here's the minimal working PyQt example,

import sys
from PyQt5.Qt import QDesktopServices, QUrl, QApplication, QColor, Qt
from PyQt5.QtWidgets import QTextEdit


class MyWidget(QTextEdit):

    def mousePressEvent(self, e):
        self.anchor = self.anchorAt(e.pos())
        if self.anchor:
            QApplication.setOverrideCursor(Qt.PointingHandCursor)

    def mouseReleaseEvent(self, e):
        if self.anchor:
            QDesktopServices.openUrl(QUrl(self.anchor))
            QApplication.setOverrideCursor(Qt.ArrowCursor)
            self.anchor = None


app = QApplication(sys.argv)
editor = MyWidget()
cursor = editor.textCursor()
fmt = cursor.charFormat()
fmt.setForeground(QColor('blue'))
address = 'http://example.com'
fmt.setAnchor(True)
fmt.setAnchorHref(address)
fmt.setToolTip(address)
cursor.insertText("Hello world again", fmt)
editor.show()
app.exec_()
Sign up to request clarification or add additional context in comments.

2 Comments

This is the base solution I ended with. I changed it to use a mouseMoveEvent() to set the anchor and change the cursor to a PointingHand when on the anchor, and reset the cursor when not on an anchor. mousePressEvent() is not needed anymore and mouseRelease is used to open the url if the anchor is set.
Don't forget to call the super() class mousePressEvent and mouseReleaseEvent implementations from the overriden methods, or you'll lost the standard mouse interaction with the widget!
14

Using QTextBrowser is simpler (as suggested by another answer). However, if for some reason you want to use QTextEdit, try to change the text interaction flags using setTextInteractionFlags(). I think you have to enable the Qt::LinksAccessibleByMouse flag.

See Qt::TextInteractionFlag and QTextEdit::textInteractionFlags

1 Comment

Note: if you use the setTextInteractionFlag() with a QTextEdit, there's no way to detect the link was clicked. If you want to manually handle the activated link/anchor, you must use a QTextBrowser.
10

As far as I've tried, when using QTextEdit + Qt::LinksAccessibleByMouse I'm able to click on links, but no action is taken (i.e., link is not open). The only action possible is to right-click on the link and select Copy Link Location.

As mentioned, one option is using QTextBrowser. In this case you have to set the QTextBrowser::openExternalLinks property too, in order to open the link using the default browser, otherwise it will be open in the text-browser widget.

Another option, given you have a read-only text, is to use a QLabel with rich format, and using the QLabel::linkActivated signal to open the URL

label->setTextFormat(Qt::RichText);
QObject::connect(label, &QLabel::linkActivated, [](const QString & link) {
  QDesktopServices::openUrl(link);
});

1 Comment

Note: I found that if you are linking to a file to be opened in addition to using .setOpenExternalLinks I needed to add the URL scheme "file://" for the link to work on MacOS
4

You can use QTextBrowser instead of QTextEdit if it read only text.

Comments

1

In order for setTextInteractionFlags() to work the openExternalLinks property needs to be set. Since this property is not available on QTextEdit, here is a little hack to enable it.

auto &clist = edit->children();
for each (QObject *pObj in clist)
{
  QString cname = pObj->metaObject()->className();
  if (cname == "QWidgetTextControl")
    pObj->setProperty("openExternalLinks", true);
}

This does not address the mouse cursor, so you will still need to override mouseMoveEvent.

1 Comment

Slightly shorter: if(pObj->inherits("QWidgetTextControl"))...
0

If you only want to use it in read-only mode, QTextBrowser is more suitable (as mentioned already above). For editing AND following links the approach is to capture mouse events. To achieve this, you subclass QTextEdit in your own class and use it instead. Below is an example, depending on your use case you then could open a context menu to edit or follow the url or similar.

// Header my-textedit.h

#include <QTextEdit>

class MyTextEdit : public QTextEdit {
    Q_OBJECT
  public:
    MyTextEdit(QWidget *parent = nullptr);

  protected:
    void mousePressEvent(QMouseEvent *);
};

// Source
#include <QMouseEvent>
#include "my-textedit.h"

MyTextEdit::MyTextEdit(QWidget *parent){}

void MyTextEdit::mousePressEvent(QMouseEvent *e)
{
    qDebug() << "MyTextEdit" << __func__ << " anchor=" << anchorAt(e->pos());
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.