Qt 기반 CodeEditor
주로 실현해야 할 부분은 줄 번호의 표시와 선택한 줄의 하이라이트입니다.
프로젝트 구조
전체 프로그램은 세 개의 파일만 있고 가장 중요한 것은 하나의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이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Qt How to use connect between incompatible signal and slotIn this I want to call a function, that function will receive a point . But this function should be invoked by a timer's...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.