В Qt 3.1 внесено множество улучшений с целью сделать программирование с Qt более простым и продуктивным. В этой статье рассказывается, как лучше использовать новые возможности Qt в ваших проектах. Для ознакомления с полным списком изменений см. http://www.trolltech.com/developer/changes/3.1.html.
Неофициальный перевод статьи Qt 3.1 - A Better Qt выполнен с любезного разрешения Trolltech.
Основными нововведениями Qt 3.1 являются следующие:
Во множество классов Qt 3.1 были добавлены новые возможности. Некоторые из этих изменений будут оценены пользователями Qt-приложений, другие - разработчиками.
Класс QTextEdit был улучшен во многих отношениях. Но наиболее важным является появление интерактивной синтаксической подсветки, поддержка которой обеспечивается абстрактным классом QSyntaxHighlighter.
Другим существенным улучшением QTextEdit является новый режим LogText, который предназначен для отображения очень больших текстов. В этом режиме данные сохраняются в памяти очень эффективным способом и предоставляются некоторые возможности режима RichText.
Для обеспечения сжатия и декомпрессии данных QByteArray Qt 3.1 предлагает две функции: qCompress() и qUncompress().
Элементы интерфейса QToolButton, QGroupBox и QColorDialog стали более настраиваемы в Qt 3.1.
В Qt 3.1 появился класс QEventLoop, который обеспечивает более гибкое управление очередью событий. Для большинства приложений важным нововведением станет возможность поддерживать пользовательский интерфейс доступным во время продолжительной обработки данных. Это достигается следующим образом:
QEventLoop *loop = qApp->eventLoop();
loop->processEvents( QEventLoop::ExcludeUserInput );
Qt 3.1 поддерживает невидимые пункты меню. В отличие от заблокированных (disabled) пунктов, которые отображаются серым, невидимые пункты не показываются вовсе.
Чтобы сделать пункт меню невидимым, вызовите setItemVisible(id, FALSE). Чтобы сделать невидимым элемент QAction, вызовите setVisible(FALSE).
Класс компоновки QLayout предоставляет две новые функции: remove() и removeItem(), которые позволяют удалять элементы интерфейса из компоновщика. Эти функции делают возможным перемещение элементов интерфейса из одного компоновщика в другой во время выполнения.
Класс QDesktopWidget впервые появился в Qt 3.0 для обеспечения доступа к экранной информации в системах с несколькими мониторами (multi-head systems). В Qt 3.1 были добавлены функции screenGeometry() и availableGeometry(). Первая возвращает размер экрана (объект QRect), а вторая - размер области экрана, не занятой панелью задач в Windows или доком и строкой меню в Mac OS X.
Классы QHttp и QFtp являются подклассами QNetworkProtocol и предоставляют единообразный высокоуровневый интерфейс, который избавляет разработчиков от низкоуровневых деталей реализации. В Qt 3.1 интерфейсы этих классов были расширены: они могут использоваться, как прежде, но теперь они также предоставляют низкоуровневый доступ для обеспечения лучшего контроля. Оба класса работают асинхронно и могут ставить запросы в очередь.
Класс QKeySequence впервые появился в Qt 3.0 для хранения клавиатурных комбинаций (например, "Ctrl+Q"). В Qt 3.1 использование слова "sequence" (последовательность) в названии класса полностью себя оправдало, и много-клавишные комбинации, такие как "Ctrl+X,Ctrl+S" и "Alt+M,A,Z" теперь поддерживаются:
action->setAccel( tr("Ctrl+X,Ctrl+S") );
action->setAccel( QKeySequence(ALT+Key_M, Key_A, Key_Z) );
Поддержка потоков в Qt 3.1 была значительно улучшена. Почти во все классы инструментов ( QString, QRegExp, QValueList и т.д.) была добавлена поддержка реентерабельности (reentrancy). Если Qt была скомпилирована с поддержкой многопоточности, для QApplication::postEvent() и некоторых других функций теперь обеспечивается потоко-независимое выполнение (thread-safety). В документации Qt теперь четко указывается, поддерживает ли класс или функция эти возможности.
В каждой версии Qt появляются новые или перегруженные для удобства функции. Qt 3.1 включает некоторые функции, которые потенциально могут изменить ваш код.
Часто встречается такое использование API QWidget:
void MyWidget::showChildWidget( bool showIt )
{
if ( showIt )
childWidget->show();
else
childWidget->hide();
}
С Qt 3.1 теперь можно писать так:
childWidget->setShown( showIt );
Обе функции: setShown() и противоположная ей setHidden(), являются слотами, поэтому вы можете легко их связывать с сигналами, указывая при этом параметр bool.
В предыдущих версиях Qt при конвертировании строк из 8-битного формата в
QString предполагалось, что используется кодировка Latin-1. Теперь
это может быть изменяемо. Например, следующий код инициализирует переменную
типа QString строкой на корейском
"
":
QTextCodec::setCodecForCStr
ings(
QTextCodec::codecForName("EUC-KR") );
str = "\273\363\300\247 \265\360\267\272\305\344\270\256";
В обычной ситуации корейский программист мог бы просто ввести этот текст в файл, используя кодировку EUC-KR:
str = "
";
В редакторе с поддержкой Latin-1 этот файл выглядел бы следующим образом:
str = "╩Сю╖ ╣П╥╨еД ╝";
Это небольшое дополнение позволяет использовать для написания кода программ любые кодировки.
Большинство разработчиков используют класс QSizePolicy только в паре с Qt Designer. Но если вы пишите код самостоятельно, то вы можете заменить строку:
widget->setSizePolicy( QSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Fixed) );
следующей:
widget->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
В предыдущих версиях Qt была доступна только одна перегруженная функция QString::replace(), которая заменяла в строке все совпадения с первым аргументом QRegExp своим вторым аргументом. Это приводило к использованию тривиальных регулярных выражений, например:
str.replace( QRegExp("\r\n"), "\n" );
В Qt 3.1 функция QString::replace() перегружена функцией, которая в качестве своего первого аргумента использует тип QString:
str.replace( "\r\n", "\n" );
Это быстрее работает и избавляет от необходимости включать <qregexp.h>.
Возможности перегруженных функций QString::replace() были расширены за счет следующих изменений:
Совместимость с STL-контейнерами впервые появилась в Qt 3.0. В Qt 3.1 также поддерживается совместимость со стандартным классом C++ std::string. В результате теперь вы можете писать так:
std::string stroustrup = "Hello";
QString eng = stroustrup;
и так:
QString nord = "World";
std::string stroustrup = nord;
По умолчанию предполагается, что класс std::string для хранения строк использует кодировку Latin-1. Вы можете изменить такое поведение глобально, вызвав функцию QTextCodec::setCodecForCStrings().
Класс QMap предлагает очень быстрый поиск, вставку и удаление в словаре. Удобный синтаксис обеспечивается перегрузкой операторов C++. Но в интерфейсе Qt часто используется класс QValueList (или QStringList), поэтому вам приходилось извлекать все ключи:
QStringList keys;
QMap<QString, int>::ConstIterator it = map.begin();
while ( it != map.end() ) {
keys.append( it.key() );
++it;
}
В Qt 3.1 это делается значительно проще:
QStringList keys = map.keys();
Функция QMap::values() теперь в качестве результата может возвращать список QValueList:
QValueList <int> values = map.values();
Функция QString::startsWith() впервые появилась в Qt 2.2, а функция QString::endsWith() - в Qt 3.0. Хотя это и выходит за рамки статьи о Qt 3.1, многим разработчикам эти функции все же не известны. Прежний стиль:
if ( url.left(5) == "http:" &&
(url.right(5) == ".html" || url.right(4) == ".xml") )
Новый стиль:
if ( url.startsWith("http:") &&
(url.endsWith(".html") || url.endsWith(".xml")) )
Новый стиль проще, меньше подвержен ошибкам и немного уменьшает размер выполнимого файла.
Новый класс QMutexLocker упрощает блокировку и разблокировку потоков. Это очень простой класс: его конструктор блокирует выполнение других потоков в определенном месте кода, а его деструктор разблокирует их. Вот пример:
int complex_function( int flag )
{
QMutexLocker locker( &my_mutex );
if ( flag == 0 || flag == 1 ) {
return less_complex_function( flag );
} else if ( flag > 10 ) {
return -1;
}
return 0;
}
Такой код меньше подвержен ошибкам, чем вызов QMutex::lock() в начале функции и QMutex::unlock() перед оператором "return".