2012-06-13 33 views
3

我正在編寫一個文本編輯器,並在GUI中使用Qt。我是Qt的noob,我很難做到這一點。在QPlainTextEdit的第80列畫一條線

我需要在QPlainTextEdit的第80列畫一條線,但我真的不知道如何。我正在使用QPainter,但我無法做到,沒有任何幫助?

回答

10

下面是我該怎麼做。毫無疑問,這並非微不足道。確定第80列位置的輸入是:

  1. 80 x浮點中的平均字符寬度。使用整數值會將舍入誤差放大80倍。因此使用QFontMetricsF

  2. 由滾動條引起的偏移量來自contentOffset()。使用horizontalScrollbar()->value()會很糟糕。後者目前可行,但依賴於實現特定的細節。 QPlainTextEdit恰好將滾動條值映射到像素 - 誰知道它明天是否會改變。它沒有記錄,因此屬於未指定的行爲。

  3. QTextDocument實施自己的保證金,可通過documentMargin()獲得。

另一個缺陷:你必須從QAbstractScrollArea派生的任何類搽viewport() - 和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"