How to get the xy position of a text in a QTextEdit?
-
I'm trying to render a square containing the color when its a hex color string:
How i could get the
xy
position of thetext
passed to thehighlightBlock
function
relative to theQTextEdit
area?I tried using
cursorRect
but I'm not figuring out how to properly save the text position, and if there's a "better" function for getting thetext
position.Work in progress:
class TextEdit : public QTextEdit { public: QRect colorRect; QColor color; TextEdit(QWidget* parent) : QTextEdit(parent) {}; void paintEvent(QPaintEvent* event) { QTextEdit::paintEvent(event); if (color.isValid()) { QPainter painter(viewport()); painter.setRenderHint(QPainter::Antialiasing); painter.setPen(Qt::NoPen); painter.setBrush(color); painter.drawRect(colorRect); } } }; class HtmlSyntax : public QSyntaxHighlighter { public: TextEdit* textEdit; QRegularExpression hexColorPattern = QRegularExpression("#[0-9A-Fa-f]{6}\\b"); HtmlSyntax(TextEdit* parent) : QSyntaxHighlighter(parent), textEdit(parent) {} protected: void highlightBlock(const QString& text) override { QRegularExpressionMatchIterator matchIterator = hexColorPattern.globalMatch(text); while (matchIterator.hasNext()) { QRegularExpressionMatch match = matchIterator.next(); QString hexColor = match.captured(0); QColor color(hexColor); if (color.isValid()) { qDebug() << hexColor; //qDebug() << text; //if (text == hexColor) //{ QRect r = textEdit->cursorRect(); textEdit->colorRect = QRect(r.x(), r.y(), 16, 16); textEdit->color = color; textEdit->viewport()->update(); //} QTextCharFormat colorFormat; colorFormat.setForeground(color); setFormat(match.capturedStart(), match.capturedLength(), colorFormat); } } } }; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::QtWidgetsApplication14Class()) { ui->setupUi(this); TextEdit* textEdit = new TextEdit(this); textEdit->setText(R"( #ff0000 ddd aa #ba00ff sdsd #00ff00 abbc #00ffb4 xxxx )"); setCentralWidget(textEdit); HtmlSyntax* htmlSyntax = new HtmlSyntax(textEdit); }
-
@Joeyy said in How to get the xy position of a text in a QTextEdit?:
but I'm not figuring out how to properly save the text position
What does this mean? Save where?
-
@jsulm Hi, I'm trying to render a colored square in front of each hex string -that represents a color-. I will also use the "square" positions, to detect when any of them get clicked so I can run a custom widget. The code I post is a work in progress, I'm not figuring out how to get each "hex string" position, to use at the QPaintEvent.
-
@Joeyy Maybe https://doc.qt.io/qt-6/qsyntaxhighlighter.html would be better?
-
@jsulm
User code above already hasclass HtmlSyntax : public QSyntaxHighlighter
, so OP is there already.@Joeyy
I don't know, just an observation.QTextEdit
and/orQSyntaxHighlighter
are both document-based. That means they expect to work from text. I don't know how easy it will be for you, you are trying to insert and maintain a "graphical rectangle" in the middle of the document text. My thought would be, e.g. at any point the layout of the lines from the text might be changed, how would you keep up with this for your graphical rectangles? I don't suppose such exists, but if the text font can do a "filled-block" character (whose color you can alter) that would seem a better fit. -
@Joeyy
As I wrote I think it would have to be IF the font you are using defines such a character. I have no idea which fonts might do that. I do not know of an HTML entity for that, I think it would have to be a font feature.Wait a minute. There is a Unicode character https://www.htmlsymbols.xyz/unicode/U+2588 "Full block" character
This character is typically used in creating graphical displays on a text-based terminal, for drawing diagrams, or for other graphical representation purposes within a text. It appears as a solid rectangle, filling the entire area of a character space. It's also frequently used in progress bars, bar graphs, and other user interface elements where a block of solid color can represent data or status visually.
Just what you seem to want! Can you put that into HTML (I don't know)? Oh, yes, it includes there "HTML Forms and Input", looks like
<span>█</span>
would do it, produces █ :) Now you need to figure if you can get that intoQTextEdit
/QSyntaxHighlighter
! -
@JonB it would help but I would still need to know their position to detect when any of them get clicked and modify the color in front of it.
I'm trying to achieve something like this, from VSCode:
When a valid hex string is entered it renders a "rectangle", you can click it and it modifies the hex string with the color selected in the widget.
-
@Joeyy
But the difference is (I assume) this way it can be done by text coordinates, not trying to draw graphics things. You only need to know what character position the user is clicking into, then you can do something about going back/forward from there to find the block. And I presumeQTextEdit
can tell you where the cursor is in character rather than coordinate terms. -
@JonB Oh I see, I think I got what you mean.
Do you have any idea how I could insert/remove the square according to when it detects a hex string in thehighlightBlock
function?I have modified the function to:
void highlightBlock(const QString& text) override { QRegularExpressionMatchIterator matchIterator = hexColorPattern.globalMatch(text); int offset = 0; // To keep track of the insertion offset while (matchIterator.hasNext()) { QRegularExpressionMatch match = matchIterator.next(); QString hexColor = match.captured(0); QColor color(hexColor); if (color.isValid()) { // Insert the "■" symbol in front of the hexColor string QString coloredSymbol = "<span style=\"color:" + color.name() + ";\">■</span>"; textEdit->insertHtml(coloredSymbol); QTextCharFormat colorFormat; colorFormat.setForeground(color); // Apply the color format to the hexColor string setFormat(match.capturedStart() + offset, match.capturedLength(), colorFormat); // Increment the offset by the length of the inserted symbol offset += coloredSymbol.length(); } } }
Now:
-
This a new attempt, I'm not figuring out how to move the cursor to the correct position and also check if it doesn't already contains a ■ after the hex string:
class HtmlHighlighter : public QSyntaxHighlighter { public: TextEdit* textEdit; QRegularExpression colorPattern = QRegularExpression("#[0-9A-Fa-f]{6}"); HtmlHighlighter(TextEdit* parent) : QSyntaxHighlighter(parent), textEdit(parent) {} protected: void highlightBlock(const QString& text) override { setCurrentBlockState(0); int startIndex = 0; if (previousBlockState() != 1) startIndex = text.indexOf(colorPattern); while (startIndex >= 0) { QRegularExpressionMatch match = colorPattern.match(text, startIndex); int endIndex = match.capturedStart(); int colorLength = 0; if (endIndex == -1) { setCurrentBlockState(1); colorLength = text.length() - startIndex; } else colorLength = endIndex - startIndex + match.capturedLength(); QString hexColor = match.captured(0); QColor color(hexColor); if (color.isValid()) { QTextCharFormat colorFormat; colorFormat.setForeground(color); setFormat(startIndex, colorLength, colorFormat); startIndex = text.indexOf(colorPattern, startIndex + colorLength); qDebug() << "startIndex: " << startIndex << "endIndex:" << endIndex; QTextCursor cursor(document()); cursor.setPosition(endIndex); cursor.insertHtml("<span style=\"color:" + color.name() + ";\">■</span>"); } } } };