Если приложение использует текстовое поле для ввода данных, то заметно упростить жизнь пользователю может подсветка синтаксиса. Не зря этот прием весьма интенсивно используется во всех IDE и текстовых редакторах для программистов.
В Qt подсветку синтаксиса легко реализовать с помощью QSyntaxHighlighter
, принцип работы которого основан на паттерне Посетитель.
Создадим приложение, которое умеет подсвечивать введенный фрагмент текста:
Заголовочный файл mainwidget.h
:
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
#include <QSyntaxHighlighter>
namespace Ui {
class MainWidget;
}
class SyntaxHighlighter;
// ********************************************************************************
class MainWidget : public QWidget {
Q_OBJECT
public:
explicit MainWidget( QWidget* parent = 0 );
~MainWidget();
private slots:
void onFind();
private:
Ui::MainWidget* ui;
SyntaxHighlighter* m_highlighter;
};
// ********************************************************************************
class SyntaxHighlighter : public QSyntaxHighlighter {
public:
SyntaxHighlighter( QTextDocument* parent );
void highlightBlock( const QString& text );
void setHighlightedString( const QString& str );
private:
QString m_highlightedString;
};
#endif // MAINWIDGET_H
Здесь мы определяем главный виджет приложения и нашу реализацию класса подсветки синтаксиса, которая наследует QSyntaxHighlighter
. Обратите внимание, что в конструкторе SyntaxHighlighter
передается указатель на QTextDocument
, к которому и привязывается подсветка синтаксиса.
Непосредственная реализация подсветки сосредоточена в виртуальной функции highlightBlock()
. А строка, которую нужно подсветить, мы задаем с помощью нашей функции setHighlightedString()
.
Реализация mainwidget.cpp
:
#include "mainwidget.h"
#include "ui_mainwidget.h"
// ********************************************************************************
MainWidget::MainWidget( QWidget* parent ) :
QWidget( parent ),
ui( new Ui::MainWidget ) {
ui->setupUi( this );
m_highlighter = new SyntaxHighlighter( ui->txt->document() );
connect( ui->bnFind, SIGNAL( clicked( bool ) ), SLOT( onFind() ) );
}
MainWidget::~MainWidget() {
delete ui;
}
void MainWidget::onFind() {
if( m_highlighter ) {
m_highlighter->setHighlightedString( ui->edSearchInput->text() );
}
}
// ********************************************************************************
SyntaxHighlighter::SyntaxHighlighter( QTextDocument* parent ) :
QSyntaxHighlighter( parent ) {
}
void SyntaxHighlighter::highlightBlock( const QString& text ) {
if( m_highlightedString.isEmpty() ) {
return;
}
QTextCharFormat fmt;
fmt.setBackground( Qt::yellow );
const int LEN = m_highlightedString.length();
for(
int index = text.indexOf( m_highlightedString );
0 <= index;
index = text.indexOf( m_highlightedString, index + LEN )
) {
setFormat( index, LEN, fmt );
}
}
void SyntaxHighlighter::setHighlightedString( const QString& str ) {
m_highlightedString = str;
rehighlight();
}
Ключевой частью реализации является фрагмент:
void SyntaxHighlighter::highlightBlock( const QString& text ) {
if( m_highlightedString.isEmpty() ) {
return;
}
QTextCharFormat fmt;
fmt.setBackground( Qt::yellow );
const int LEN = m_highlightedString.length();
for(
int index = text.indexOf( m_highlightedString );
0 <= index;
index = text.indexOf( m_highlightedString, index + LEN )
) {
setFormat( index, LEN, fmt );
}
}
Этой функции автоматически передается каждый блок текста (в простейшем случае по одной строке), в котором проводится поиск, и в случае обнаружения соответствия задается формат QTextCharFormat
.
Также обратите внимание на следующую функцию:
void SyntaxHighlighter::setHighlightedString( const QString& str ) {
m_highlightedString = str;
rehighlight();
}
Вызов rehighlight()
обеспечивает принудительный запуск процесса подсветки синтаксиса для вновь заданной строки.
QSyntaxHighlighter
позволяет реализовать и более сложные виды подсветки. Например, обрабатывать случаи многострочной подсветки, как в случаях многострочных комментариев /* … */
.
Скачать пример использования QSyntaxHighlighter