Qt 기반 CodeEditor

6140 단어 qt
우선 최종 효과를 살펴보자.
주로 실현해야 할 부분은 줄 번호의 표시와 선택한 줄의 하이라이트입니다.
프로젝트 구조
전체 프로그램은 세 개의 파일만 있고 가장 중요한 것은 하나의CodeEditor 클래스만 있습니다. 이것은 QPlainTextEdit에서 계승된 것입니다. 이 클래스는 일반적인 TextEdit보다 풍부한 텍스트 편집기에 적합합니다.
헤더 파일
//codeeditor.h #ifndef CODEEDITOR_H #define CODEEDITOR_H  #include  #include   QT_BEGIN_NAMESPACE class QPaintEvent; class QResizeEvent; class QSize; class QWidget; QT_END_NAMESPACE  class LineNumberArea;  //![codeeditordefinition]  class CodeEditor : public QPlainTextEdit {     Q_OBJECT  public:     CodeEditor(QWidget *parent = 0);      void lineNumberAreaPaintEvent(QPaintEvent *event);     int lineNumberAreaWidth();  protected:     void resizeEvent(QResizeEvent *event);  private slots:     void updateLineNumberAreaWidth(int newBlockCount);     void highlightCurrentLine();     void updateLineNumberArea(const QRect &, int);  private:    
        LineNumberArea *lineNumberArea;
};//![codeeditordefinition]//![extraarea]class LineNumberArea : public QWidget{public: LineNumberArea(CodeEditor *editor) : QWidget(editor) { codeEditor = editor; } QSize sizeHint() const { return QSize(codeEditor->lineNumberAreaWidth(), 0); }protected: void paintEvent(QPaintEvent *event) { codeEditor->lineNumberAreaPaintEvent(event); }private:
  Code Editor *codeEditor;};//![extraarea]#endif  
  
: QPlainTextEdit CodeEditor QWidget LineNumberArea。

: QPlainTextEdit protected , CodeEditor 。

, , , , slot:updateLineNumberWidth() updateLineNumberArea()。


cpp

//codeeditor.cpp #include   #include "codeeditor.h"  //![constructor]  CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent) {     lineNumberArea = new LineNumberArea(this);      connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));     connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));     connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));      updateLineNumberAreaWidth(0);     highlightCurrentLine(); }  //![constructor]  //![extraAreaWidth]  int CodeEditor::lineNumberAreaWidth() {     int digits = 1;     int max = qMax(1, blockCount());     while (max >= 10) {         max /= 10;         ++digits;     }      int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;      return space; }  //![extraAreaWidth]  //![slotUpdateExtraAreaWidth]  void CodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */) {      setViewportMargins(lineNumberAreaWidth(), 0, 0, 0); }  //![slotUpdateExtraAreaWidth]  //![slotUpdateRequest]  void CodeEditor::updateLineNumberArea(const QRect &rect, int dy) {     if (dy)         lineNumberArea->scroll(0, dy);     else         lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height());      if (rect.contains(viewport()->rect()))         updateLineNumberAreaWidth(0); }  //![slotUpdateRequest]  //![resizeEvent]  void CodeEditor::resizeEvent(QResizeEvent *e) {     QPlainTextEdit::resizeEvent(e);      QRect cr = contentsRect();     lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height())); }  //![resizeEvent]  //![cursorPositionChanged]  void CodeEditor::highlightCurrentLine() {     QList<:extraselection> extraSelections;      if (!isReadOnly()) {         QTextEdit::ExtraSelection selection;                  QColor lineColor = QColor(Qt::yellow).lighter(160);          selection.format.setBackground(lineColor);         selection.format.setProperty(QTextFormat::FullWidthSelection, true);         selection.cursor = textCursor();         selection.cursor.clearSelection();         extraSelections.append(selection);     }      setExtraSelections(extraSelections); }  //![cursorPositionChanged]  //![extraAreaPaintEvent_0]  void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event) {     QPainter painter(lineNumberArea);     painter.fillRect(event->rect(), Qt::lightGray);  //![extraAreaPaintEvent_0]  //![extraAreaPaintEvent_1]     QTextBlock block = firstVisibleBlock();     int blockNumber = block.blockNumber();     int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();     int bottom = top + (int) blockBoundingRect(block).height(); //![extraAreaPaintEvent_1]  //![extraAreaPaintEvent_2]     while (block.isValid() && top <= event->rect().bottom()) {         if (block.isVisible() && bottom >= event->rect().top()) {             QString number = QString::number(blockNumber + 1);             painter.setPen(Qt::black);             painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),                              Qt::AlignRight, number);         }          block = block.next();         top = bottom;         bottom = top + (int) blockBoundingRect(block).height();         ++blockNumber;     } } //![extraAreaPaintEvent_2] 
cpp에서 먼저 클래스의 구조 함수로 개인 구성원을 초기화하고 해당하는 signal과 slot을 연결한다.linenumbeearea의 폭을 계산하고 첫 줄을 밝게 하는 것도 필수적이다.line Number Area Width (): Line Number Area의 폭을 계산하는 데 사용되며, 최대 줄 수를 얻고, 그 수를 숫자 9의 폭과 곱하고, 3의 간격을 더하면 된다.업데이트 라인 Number Area Width (int): 라인 Number Area의 폭을 업데이트합니다. 주로 setViewport Margins () 를 사용하고 내부 간격을 설정합니다.줄 수가 계속 늘어나면 왼쪽의 안쪽 간격만 늘리면 된다.업데이트 라인 넘버아레아(const QRect &rect, int dy): 줄이 바뀔 때 라인 넘버아레에 대한 업데이트 리서치 이벤트(QResize Event *e): 창 크기가 바뀔 때 라인 넘버아레의 크기도 변경됩니다.highlightCurrentLine(): 커서 위치가 변경되면 강조 위치도 변경됩니다.line Number Area Paint Event(QPaint Event*event): 주로 줄 번호를 표시하는데 먼저 검은색 배경을 그린 다음에 줄 번호를 순환적으로 그립니다.plain text edit에서는 각 행에 하나의 QText Block만 포함합니다.따라서 줄이 접히면 줄 번호가 정확하지 않을까 봐 걱정하지 않아도 된다.두 번의 판단을 해야 하며, 한 번은calid이고, 순서는visible이다.

좋은 웹페이지 즐겨찾기