I'm writing a text editor and using Qt for the GUI. I'm a noob in Qt and I'm having trouble to do this.
I need to draw a line in the column 80 of the QPlainTextEdit but I really don't know how. I'm using QPainter but I just can't get it right, any help?
Here's how I'd do it. It's admittedly not entirely trivial. The inputs to determining the 80th column position are:
80 x the average character width in floating point. Using the integer value will magnify the roundoff error by a factor of 80. Thus use QFontMetricsF
.
The offset due to scrollbars comes from contentOffset()
. It'd be bad to use horizontalScrollbar()->value()
. The latter currently works, but relies on the implementation-specific detail. QPlainTextEdit happens to map scrollbar values to pixels -- who knows if it won't change tomorrow. It's not documented, thus falls under unspecified behavior.
The QTextDocument
implements its own margin, available via documentMargin()
.
Another pitfall: you must paint on the viewport()
in any class that derives from QAbstractScrollArea
-- and QPlainTextEdit
does so. If you don't, your paintEvent
becomes a no-op. It's documented, but you must be clever enough to actually look into documentation. I'd consider it a bad corner case of an API that does something unexpected. In every other paintEvent
, you simply create QPainter p
or QPainter p(this)
and it works.
Note: this is tested, compileable code.
//main.cpp
#include <cmath>
#include <QtWidgets>
class Edit : public QPlainTextEdit
{
public:
Edit(QWidget * parent = 0) : QPlainTextEdit(parent) {}
protected:
void paintEvent(QPaintEvent * ev)
{
QPlainTextEdit::paintEvent(ev);
const QRect rect = ev->rect();
const QFont font = currentCharFormat().font();
int x80 = round(QFontMetricsF(font).averageCharWidth() * 80.0)
+ contentOffset().x()
+ document()->documentMargin();
QPainter p(viewport());
p.setPen(QPen("gray"));
p.drawLine(x80, rect.top(), x80, rect.bottom());
qDebug() << x80 << contentOffset() << document()->documentMargin() << font << endl;
}
};
static QString filler()
{
QString str;
for (char c = '0'; c < '9'; ++ c) {
str.append(QString(10, c));
}
return str;
}
int main(int argc, char ** argv)
{
QApplication app(argc, argv);
Edit ed;
QTextCharFormat fmt = ed.currentCharFormat();
fmt.setFontFamily("courier");
fmt.setFontFixedPitch(true);
ed.setCurrentCharFormat(fmt);
ed.setLineWrapMode(QPlainTextEdit::NoWrap);
qDebug() << fmt.font() << endl;
ed.setPlainText(filler());
ed.show();
app.exec();
}
#include "main.moc"