QTextCursor::mergeBlockFormat() doesn't set format.
-
I have this function for setting block format:
void PasswordShowArea::updateBlockFormat() { insertPlainText("Some text"); QTextBlockFormat fmt = textCursor().blockFormat(); fmt.setTextIndent(g_lineNumberAreaWidth + g_lineNumberRightMargin); fmt.setLineHeight(fontMetrics().height() * 2, QTextBlockFormat::LineDistanceHeight); textCursor().mergeBlockFormat(fmt); }
Idea was to se block format in constructor but it doesn't work as expected. The function itself is called but neither text is inserted nor block format changed:
PasswordShowArea::PasswordShowArea(QWidget *parent) : QTextEdit(parent) { init(); //doesn't work // updateBlockFormat(); // works - gpt4 suggest QTimer::singleShot(0, this, &PasswordShowArea::updateBlockFormat); }
void PasswordShowArea::init() { QObject::connect(document()->documentLayout(), &QAbstractTextDocumentLayout::update, this, &PasswordShowArea::updatePasswordShowArea); setTextColor(palette().color(QPalette::Text)); }
Any ideas why this happen?
P.S. gpt suggested that the problem may be that the object at the time theupdateBlockFormat()
is called is not fully initialized -
-
@Khamza
First to answer your question. Your new code delays the update till after the text edit has been shown. In that sense it is similar to theQTimer
approach. For unknown reason you are claiming the code does not work correctly until after the text edit has been shown.There are cases in Qt which this is necessary. In particular sizes of widgets are not calculated till they are actually shown, so code which requires to know a size is often delayed in one of the above two fashions.
HOWEVER I was never convinced by your assertion "The function itself is called but neither text is inserted nor block format changed:". While I could believe that possibly an operation on
textCursor()
might require the text edit to be shown I never thought thatinsertPlainText()
for sure would depend on that. It should be callable any time, including e.g. during construction.I have now had time to create a minimal repro. Here are the 3 files:
#include "passwordshowarea.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); PasswordShowArea w; w.show(); return a.exec(); }
#ifndef PASSWORDSHOWAREA_H #define PASSWORDSHOWAREA_H #include <QTextEdit> class PasswordShowArea : public QTextEdit { Q_OBJECT public: PasswordShowArea(QWidget *parent = nullptr); private: void init(); void updateBlockFormat(); }; #endif // PASSWORDSHOWAREA_H
#include <QAbstractTextDocumentLayout> #include <QTimer> #include "passwordshowarea.h" PasswordShowArea::PasswordShowArea(QWidget *parent) : QTextEdit(parent) { init(); //doesn't work updateBlockFormat(); // works - gpt4 suggest // QTimer::singleShot(0, this, &PasswordShowArea::updateBlockFormat); } void PasswordShowArea::init() { // QObject::connect(document()->documentLayout(), &QAbstractTextDocumentLayout::update, // this, &PasswordShowArea::updatePasswordShowArea); setTextColor(palette().color(QPalette::Text)); } void PasswordShowArea::updateBlockFormat() { insertPlainText("Some text"); QTextBlockFormat fmt = textCursor().blockFormat(); fmt.setTextIndent(20); fmt.setLineHeight(fontMetrics().height() * 2, QTextBlockFormat::LineDistanceHeight); fmt.setBackground(Qt::red); textCursor().mergeBlockFormat(fmt); }
I have made couple of tiny tweaks where I did not have all of your code. I added
fmt.setBackground(Qt::red);
so that we had something to see. And here is what I get:You can see that not only do I get the inserted text but I do also get the
QTextBlockFormat
changes. Identical if I change it to only callupdateBlockFormat()
on the delayed timer. Ubuntu 24.04, Qt 6.4.2.Sooo.... I suggest you try just this code.
-