Changing "CodeEditor" example code.
-
There is example from code editor.
I want to draw both numbers and text from myCodeEditor::paintEvent()
without callingQTextEdit::paintEvent()
from it because it will draw text twice. Also i don't want to use additionalLineNumberArea
class.
The problem is that i can't pass text fromQTextEdit::insertPlainText()
to myCodeEditor::paintEvent()
.
How can i do that?
Or should i use another approach?
P.S I useQTextEdit
instead ofQPlainTextEdit
because of rich text support. -
@Khamza said in Changing "CodeEditor" example code.:
from my CodeEditor::paintEvent() without calling QTextEdit::paintEvent() from it because it will draw text twice.
Why would anything draw twice. If you call the base
paintEvent()
from a derived class don't have the overrider paint stuff the base is doing.can't pass text from QTextEdit::insertPlainText() to my CodeEditor::paintEvent()
That does not sound like something you should want or need to do.
If you have a working example why do you want to change it with things like "Also i don't want to use additional LineNumberArea class."? Aren't you overcomplicating?
-
@JonB Thank you for your reply.
I want to use my own paintEvent because additionally i want to draw lines between strings as here:
So i thought it would be much easier to maintain code in future with this approach and to draw all three parts(line numbers, strings, lines between) in one place. Also i don't need some extra functionality for my line numbers.
And if i use two classes i have to draw in two functions: one for line numbers and other for "underlines".
Despite all the above you think that using two separate classes is good approach and not overkill for my case?Thank you!
-
@Khamza said in Changing "CodeEditor" example code.:
The problem is that i can't pass text from QTextEdit::insertPlainText() to my CodeEditor::paintEvent().
The data structure backing
QTextEdit
(andQPlainTextEdit
) isn't a simpleQString
, it is aQTextDocument
. Logically, a text document is a collection of text blocks (with associated formats); the blocks are also arranged in various rich text structures like frames, tables, lists etc. Make sure you understand the relevant documentation.When you call convenience methods like
QTextEdit::insertPlainText
, they just use the text cursor interface under the hood to create the requisite elements in the editor's backingQTextDocument
. So if you want programmatic access to the editor's text, you need to get the document withQTextEdit::document
and iterate over it using whatever strategy is appropriate for your needs.@Khamza said in Changing "CodeEditor" example code.:
I want to use my own paintEvent because additionally i want to draw lines between strings as here:
You can draw extra stuff directly on the editor in its'
paintEvent
for sure if that's what you feel is easier for you to write and maintain. The Code Editor example uses a separate widget for the line number area as it is probably somewhat easier to reason about managing its' size and position by having it in the the scroll view's viewport margin area (and it being a sink for input events intersecting with it is probably the more expected UX) but it is absolutely not essential. You can take another approach to ensuring that there is sufficient space left, and draw the line numbers (and any other decorations) directly into that space.What I don't suggest doing is to try to draw the text itself yourself. If you change anything about the text positioning relative to how the default layout will do it things like selecting text by mouse, caret movements and scrolling will break. There are multiple things that you need to tell
QTextEdit
about where the text exactly is and how big is it for all the text interaction behavior to be correct. This is abstracted by theQAbstractTextDocumentLayout
interface, and if you want custom text positioning the "correct" thing to do is to implement it. However it is rather hard to get right.What you really should do if you can is to use custom block and character formats to ensure that the default text layout will leave sufficient space (e.g look at the
setLeftMargin
,setBottomMargin
etc methods ofQTextBlockFormat
). In yourpaintEvent
override, first call the parent for it to draw the text, and then draw the horizontal lines, line numbers and everything else you'd like, using the default text document layout to give you the bounding rectangles of text blocks to guide you. -
Thank you for your response.
So finally i used only one class and thy to draw everything in it. And i came to thispaintEvent()
which looks better and i think much more easy to understandvoid PasswordShowArea::paintEvent(QPaintEvent *event) { QTextEdit::paintEvent(event); QPainter painter(viewport()); fillLineNumberArea(&painter); QTextDocument *doc = document(); QAbstractTextDocumentLayout *lay = doc->documentLayout(); // custom firstVisibleBlock() works fine. for (QTextBlock block = firstVisibleBlock(); block.isValid() && block.isVisible(); block = block.next()) { painter.drawText(0, cursorRect(QTextCursor(block)).y(), 40, lay->blockBoundingRect(block).height() , Qt::AlignRight, QString::number(block.blockNumber() + 1)); int pointBetweenTwoStrings = lay->blockBoundingRect(block).top() + lay->blockBoundingRect(block).height() + block.blockFormat().lineHeight() / 2; painter.drawLine(0, pointBetweenTwoStrings, event->rect().width(), pointBetweenTwoStrings); } }
But there are some bugs which appear as i think because of scroll.
No scroll:
After some scroll:
How do you think this problem can be solved? I really want to use this approach.
Thank you! -
-
@Khamza It is quite hard to tell. The piece of code you pasted has several issues unfortunately, and it would very hard to say what the exact cause it without the whole thing to reproduce.
I'll say that the most pressing problem in the code is that you are using values that are in document coordinates (which is what the rectangle that
QAbstractTextDocumentLayout::blockBoundingRect
returns is in) to calculate parameters for aQPainter
which works in viewport coordinates. These are not the same, especially when there are scroll bars shown, and in my experience the main cause of issues around scrolling.That said, it wouldn't explain the text itself just disappearing when scrolling back up; I'd expect it to just be garbled. First try to comment out your
paintEvent
to see if text is drawn correctly at the expected positions when scrolling back and forth - perhaps something in the formats isn't right. Otherwise, please post a complete yet minimal project that reproduces the problems you see.