Limited QTextEdit – do it the right way
Recently during development, I encountered a problem in adding a character limit to the QTextEdit element. I will describe the most frequently suggested solution, which is in my opinion wrong. And the other way, which was usually suggested by more experienced developers, but not presented in the code.
The wrong way
Usually, you can find the following solution, which is quite intuitive in Qt:
- Create
textChanged
event handler. - Extract
QTextEdit
text, and check its length. - Modify it the way you want and call
textEdit->setText
with modified text. - Update
QTextEdit
cursor (carriage) position.
What is wrong with that solution? The problem is that calling setText in textChanged handler is a way to create endless recursion. Qt signals and slots are a nice way to decouple things, but unfortunately, some scenarios can lead you to problems.
Even if this way will work in your environment, it is strongly related to the Qt implementation. In my case, the program ends on Segmentation fault.
The right way
The right way, proposed by more advanced developers on the Qt forum looks like that:
- Create a new class, for example,
LimitedTextEdit
which derives fromQTextEdit
. - Overload
keyPressEvent
andkeyReleaseEvent
methods. Their content should check if the text, extracted withtoPlainText()
matches the character limit. If it does, the base class method should be called (keyPressEvent
orkeyReleaseEvent
), otherwise, it will filter out the pressed key. - Promote your
QTextEdit
toLmitedTextEdit
in Design editor.
Below you can find my implementation, limitedtextedit.h
:
#ifndef LIMITEDTEXTEDIT_H
#define LIMITEDTEXTEDIT_H
#include <QTextEdit>
class LimitedTextEdit : public QTextEdit
{
public :
LimitedTextEdit(QWidget *parent = 0) : QTextEdit(parent) { }
virtual ~LimitedTextEdit() { }
protected :
virtual void keyPressEvent(QKeyEvent *e) override;
virtual void keyReleaseEvent(QKeyEvent *e) override;
};
#endif // LIMITEDTEXTEDIT_H
limitedtextedit.cpp
:
#include "limitedtextedit.h"
#define LIMITED_TEXT_EDIT_MAX 120
void LimitedTextEdit::keyPressEvent(QKeyEvent *e)
{
int len = QTextEdit::toPlainText().toAscii().length();
if (len < LIMITED_TEXT_EDIT_MAX)
{
QTextEdit::keyPressEvent(e);
}
}
void LimitedTextEdit::keyReleaseEvent(QKeyEvent *e)
{
int len = QTextEdit::toPlainText().toAscii().length();
if (len < LIMITED_TEXT_EDIT_MAX)
{
QTextEdit::keyReleaseEvent(e);
}
}
This part is scalable. You may add parsing keys, passed to the event handler, and for example, unlock arrow keys or block pasting content, Everything here is in your hands. If you want to react on a key normally, just pass it to QTextEdit
implementation. Now you have to promote your generated by a designer QTextEdit object:
After that just click Add and Promote.