在QPlainTextEdit的第80列中画一条线

时间:2012-06-13 16:44:05

标签: c++ qt qt4

我正在编写文本编辑器并使用Qt进行GUI。我是Qt的菜鸟,我很难做到这一点。

我需要在QPlainTextEdit的第80列画一条线,但我真的不知道怎么做。我正在使用QPainter,但我无法正确使用,有什么帮助吗?

1 个答案:

答案 0 :(得分:10)

我是这样做的。诚然,这并非完全无足轻重。确定第80列位置的输入是:

  1. 80 x浮点的平均字符宽度。使用整数值会将舍入误差放大80倍。因此使用QFontMetricsF

  2. 滚动条产生的偏移来自contentOffset()。使用horizontalScrollbar()->value()会很糟糕。后者目前有效,但依赖于特定于实现的细节。 QPlainTextEdit恰好将滚动条值映射到像素 - 谁知道它明天是否会改变。它没有记录,因此属于未指明的行为。

  3. QTextDocument实现了自己的保证金,可通过documentMargin()获取。

  4. 另一个陷阱:你必须在viewport()衍生的任何类中的QAbstractScrollArea上画画 - 而QPlainTextEdit这样做。如果不这样做,您的paintEvent就变成了无操作。它已被记录,但您必须足够聪明才能真正查看文档。我认为它是API的一个坏角落,可以做出意想不到的事情。在其他所有paintEvent中,您只需创建QPainter pQPainter 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"