在 QPlainTextEdit 的第 80 列中画一条线
Draw a line in column 80 of QPlainTextEdit
我正在编写一个文本编辑器并将Qt用于GUI。我是Qt的菜鸟,我很难做到这一点。
我需要在QPlainTextEdit的第80列中画一条线,但我真的不知道怎么做。我正在使用QPainter,但我就是无法正确处理,有什么帮助吗?
这是我的做法。诚然,这并不完全是微不足道的。确定第 80 列位置的输入是:
-
浮点平均字符宽度的 80 倍。使用整数值会将舍入误差放大 80 倍。因此使用
QFontMetricsF
. -
滚动条引起的偏移量来自
contentOffset()
.使用horizontalScrollbar()->value()
会很糟糕.后者目前有效,但依赖于特定于实现的细节。QPlainTextEdit碰巧将滚动条值映射到像素 - 谁知道明天它是否会改变。它没有记录,因此属于未指定的行为。 -
QTextDocument
实现自己的保证金,可通过documentMargin()
.
另一个陷阱是:你必须在任何源自QAbstractScrollArea
的类的viewport()
上绘画——QPlainTextEdit
这样做了。如果你不这样做,你的paintEvent
就变成了禁区。它有文档记录,但您必须足够聪明才能实际查看文档。我认为这是 API 的一个糟糕的极端情况,它做了一些意想不到的事情。在所有其他paintEvent
中,您只需创建QPainter p
或QPainter p(this)
即可工作。
注意:这是经过测试的可编译代码。
//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"
相关文章:
- 如何在 c++ 中确定一条指令(以字节为单位)在哪里结束,另一条指令从哪里开始?
- 如何在 Win32 中用一条线连接 2 个文本框?
- C++ 如何在同一行中和在一条线上?
- 如何在SDL2窗口上使用Cairo绘制一条白色直线
- 在Opengl中绘制一条不显示C++的线
- 为什么当 while 循环中的 if 条件变为 false 时,我的函数不输出最后一条语句?
- x86 - 为什么编译器在下一条指令中插入看似毫无意义的JMP?
- CMake似乎忽略了一条线
- 在C 中使用Legacy OpenGL(即时模式)绘制一条厚线
- 在图像标签上画一条线并计算距离
- switch 语句结束和下一条语句之间的时间是否具有确定性(与路径无关)
- 如何在OMNET++中收到来自前一个模块的所有消息后将一条消息发送到下一个模块
- 一条线和两行声明之间的差异
- C++ OpenCV:检测两条线而不是一条线(Canny & findContours)
- 如何在C++中将边列表转换为邻接矩阵,其中包含连接到顶点的边数而不是一条边?
- 为什么 fstream 打印出文件的最后一条记录
- 如何在另一条消息(M1)之前调用带有消息(M2)的lambda函数,但输出要"M2 M1"?
- 如何在子小部件而不是父窗口小部件上绘制一条线
- 在C++中,文件中的下一条记录被非法更新
- MFC:在 CRichEditCtrl 中突出显示一条线一段时间,然后恢复