在Qt的example里有个例子叫做codeeditor:
该例子演示QPlainTextEdit类的用法, 其中有个有用的功能是在编辑器的左边margin的位置显示行号。 查看它的代码就会发现, 它用的时候遍历QTextBlock的方法确定行号, 这样就带来一个问题, 也就是实际上显示的所谓“行号”其实是段落号。 这在大多数情况下没什么问题, 但遇到某些bt用户非要狂按“Shift+Enter”问题就来了。
在中可以找到对“Shift+Enter”和“Enter”行为的准确定义:
Enter | Enter | Enter | Enter | (none) | |
Shift+Enter | Meta+Enter | Shift+Enter | Shift+Enter | (none) |
所以按下“Shift+Enter”和按下“Enter”结果是不同的。 这种不同从外表看不出来, 但和codeeditor中实现显示行号的代码结合一下, 就明白无误了。
解决的方法比较曲折(当然可能有更好的方法等着大家去探索), 除了要遍历每个block, 还要用QTextBlock的方法去遍历每个QTextLine。 另外一个让人头疼的地方是还要计算出每行的y坐标, 好在合适的地方画上这个行号。 多说无益, 代码说话:
QTextBlock block = document()->begin();
int top = 0;
QTextCursor cursor(block);
cursor.setPosition(0);//move to the beginning of the document
qWarning() << document()->lineCount() << document()->blockCount();
int linenum = 0;
while(linenum < document()->lineCount())
{
for( int i = 0 ; i < block.lineCount(); i ++)
{
QTextLine line = block.layout()->lineAt(i);
//qWarning() << line.rect().toRect() << "x,y:" << line.x() << line.y();
int dx = blockBoundingGeometry(block).x();
int dy = blockBoundingGeometry(block).y();
//qWarning()<< "block offset:" << dx << dy << "content offset:" << contentOffset();
top = line.rect().translated(contentOffset()).translated( dx,dy).y();
painter.setPen(Qt::black);
painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),
Qt::AlignRight, QString::number( linenum +1));
linenum ++;
}
block = block.next();
if(!block.isValid())
{
break;
}
}