Сейчас уже доступна Qt 3.2. В этой версии появилось много новых классов и возможностей, которые вам бы наверняка захотелось должным образом использовать в своих Qt-приложениях. Большинство из них мы рассмотрим в этой статье. С полным списком изменений в Qt 3.2.0 можно ознакомиться здесь.
Неофициальный перевод статьи What's New in Qt 3.2 выполнен с любезного разрешения Trolltech.
Новый класс QSplashScreen упрощает создание экранной заставки, демонстрируемой во время загрузки приложений. Этот класс во многом схож с классом SplashScreen из четвертого выпуска Qt Quarterly. Если в своих приложениях вы уже используете SplashScreen, вы можете заменить его классом QSplashScreen. При замене помните о следующем:
Панель инструментов QToolBox, впервые появившаяся в Qt Designer 3.1, стала стандартным интерфейсным элементом Qt, который вы можете использовать в своих собственных программах.
В среде Windows элемент QToolBox имеет внешний вид стандартного для этой платформы элемента ToolBox. При использовании стилей Mac и Motif страницы, входящие в состав элемента, изображаются в виде вкладок.
Qt Designer обеспечивает полную поддержку элемента QToolBox. Для этого из списка интерфейсных элементов выберите ToolBox и затем поместите его в вашу форму. Теперь вы можете заполнить вкладки элемента точно так же, как заполняли раньше вкладки QTabWidget или QWidgetStack.
В много-поточных приложениях статические и глобальные переменные доступны для всех потоков. Если вы хотите, чтобы у каждого потока была своя копия данных, то используйте для хранения переменных новый шаблонный класс QThreadStorage. Этот класс обеспечивает механизм хранения локальных данных потока, известный также как Thread-Local Storage (TLS). До выхода Qt 3.2 это можно было сделать только с помощью платформо-зависимого API. Теперь это делается так:
В каких случаях может использоваться QThreadStorage? Обычно для хранения глобальных и статических переменных, к которым должен быть запрещен одновременный доступ из нескольких потоков. В качестве примера может послужить кэш, одновременный доступ к которому из нескольких потоков может привести к ошибкам. (В качестве альтернативного решения можно использовать QMutex.)
Часто увеличение длины строки QString приводит к повторному перераспределению памяти, как показано в следующем примере:
while (...) {
str += getChar();
}
Такое автоматическое перераспределение памяти в классе QString является приемлемым для большинства приложений. Для более гибкого управления памятью используйте три следующих функции QString:
Эти функции не изменяют значение объекта QString, а лишь влияют на скорость его работы и использование им памяти. Ниже представлен пример, в котором вызов reserve() гарантирует, что во время работы цикла while не будет перераспределяться память, а последующий вызов squeeze() обеспечивает освобождение всей неиспользуемой памяти:
QString str;
int len = 0;
str.reserve(maxLen);
while (...) {
str[len++] = getChar();
}
str.squeeze();
Механизм QString::arg() накладывает ограничения на использование символа % в строковых параметрах. Например, следующий код будет работать некорректно, если appName содержит %0, %1 или %2:
QString("%1 - %2").arg(appName).arg(fileName);
Для решения этой проблемы Qt 3.2 предлагает использовать перегруженную функцию arg() с различным числом строковых параметров. Вот как следует переписать этот участок кода, чтобы избежать возможных проблем:
QString("%1 - %2").arg(appName, fileName);
Функция arg() в качестве параметров может принимать до четырех строковых значений. Если вам необходимо передать нестроковое значение, например, int или float, воспользуйтесь для этого сначала одноаргументной версией arg(), а затем многоаргументной arg() для передачи строк.
Элемент QLineEdit теперь поддерживает ввод по маске. Маска состоит из специальных символов и разделителей. Специальные символы определяют допустимый диапазон ввода, разделители всегда видимы и не могут быть изменены. Например, в маске 990.990.990.990 девятки определяют поля опционального ввода цифр, нули - поля обязательного ввода, а точки являются разделителями. Такая маска может использоваться для ввода IP-адреса, такого как 123.54.129.255.
Маски дополняют валидаторы (validators). Основная проблема валидаторов заключалась в отсутствии визуального представления. В то же время, для контроля ввода маски могут использовать разделители.
В любой момент времени вы можете проверить введенные данные на корректность с помощью функции hasAcceptableInput(). Если в поле ввода ожидалось цифровое значение, QLineEdit не позволит ввести буквенное, однако пользователь может не вводить всю необходимую информацию, и в этом случае hasAcceptableInput() возвратит false.
Более подробную информацию об используемых в масках специальных символах и примеры готовых масок можно найти в описании свойства inputMask. Наиболее простой способ поэкспериментировать с масками - запустить Qt Designer, установить для элемента QLineEdit свойство inputMask и включить предварительный просмотр формы (Ctrl+T).
В Qt 3.0 был выполнен большой объем работ, связанный с поддержкой языков с левосторонним чтением, таких как арабский, персидский и иврит. В Qt 3.2 эта поддержка была расширена на семейство индийских языков, включая бенгальский, тамильский и деванагари.
Также в список поддерживаемых языков с левосторонним чтением был добавлен сирийский. Для поддержки этих языков со стороны Windows должен использоваться Uniscribe, а со стороны X11 - XFT и шрифты OpenType.
Класс QTabWidget теперь поддерживает угловые элементы с двух сторон поля вкладок. Эту возможность использует Qt Assistant для отображения слева и справа от поля вкладок кнопок добавления и удаления текущей вкладки.
Классы неявного совместного доступа (implicitly shared classes) QMap<K,T>, QValueList<T> и QValueVector<T> наряду с функциями begin() и end() сейчас поддерживают функции constBegin() и constEnd(). При просмотре классов-контейнеров с использованием const-итераторов функции constBegin() и constEnd() оказываются более быстрыми, чем их не-const аналоги, потому что им не нужно проверять наличие совместного доступа к данным. Для большинства приложений выигрыш в скорости при использовании этих функций окажется небольшим, но Qt сейчас использует их везде, где это возможно.
Если вы хотите использовать эти функции в своих приложениях, найдите все вхождения const_iterator или ConstIterator, например:
QValueVector<int>::const_iterator it = vec.begin();
while (it != vec.end()) {
++it;
}
и замените функции begin() и end() функциями constBegin() и constEnd():
QValueVector<int>::const_iterator it = vec.constBegin();
while (it != vec.constEnd()) {
++it;
}
Также убедитесь в том, что вы используете const_iterator вместо iterator во всех случаях, когда полученные через итератор данные не модифицируются.
Одним из нововведений в Qt 3.1 был режим LogText в QTextEdit. Этот режим был оптимизирован для просмотра больших текстов. Сейчас QTextEdit позволяет задать максимальное число строк текста для этого режима. Если это число будет превышено, верхние строки будут автоматически удаляться.
В настоящее время для использования в приложениях Qt предлагает переносимые предопределенные 64-битные целые типы Q_LLONG и Q_ULLONG. Поддержка Q_LLONG и Q_ULLONG в QVariant позволяет избежать конвертирования данных в строку и обратно при доступе к 64-битным полям SQL-баз данных. Также с целью поддержки 64-битных целых типов были расширены интерфейсы QString и QDataStream.
В классе QDialog появился новый метод setModal(bool), который делает излишним параметр bool modal конструктора этого класса. Теперь при создании собственного подкласса QDialog вам достаточно определить конструктор вида:
MyDialog(QWidget *parent
= 0, const char *name = 0);
Если вам необходимо сделать диалог модальным, вы можете либо вызвать метод exec() (который всегда показывает модальный диалог), либо последовательно вызвать setModal(true) и show(). Второй подход также позволяет сделать диалог немодальным.
Статическая функция
QMessageBox::aboutQt()<
/i>
выводит диалоговое окно About Qt. В Qt 3.2 появился одноименный слот
QApplication::aboutQt(
),
который может быть связан непосредственно с соответствующим
QAction:
aboutQtAct = new QAction(tr("About &Qt"), 0, this);
connect(aboutQtAct, SIGNAL(activated()), qApp, SLOT(aboutQt()));
Это более удобно, чем создание собственного слота aboutQt(), вызывающего статическую функцию QMessageBox::aboutQt().
Помимо информирования о том, что вы используете высококачественный инструментарий, окно About Qt показывает номер версии библиотеки Qt, использованной для сборки приложения, что может быть полезным при отладке и поддержке.
Класс QAction теперь имеет новые конструкторы, которые не требуют явного указания названия выполняемого действия. Старый стиль:
openAct = new QAction(tr("Open"), tr("&Open..."), tr("Ctrl+O"), this);
Новый стиль:
openAct = new QAction(tr("&Open..."), tr("Ctrl+O"), this);
Класс QAction достаточно умен для того, чтобы получить текст всплывающей подсказки из названия пункта меню путем удаления амперсанда ("&") и завершающих точек ("..."). В некоторых языках, например, японском, такой стиль может работать некорректно, в этих случаях используйте setToolTip().
Функции QApplication::applicat ionDirPath() и QApplication::applicationFilePath() возвращают путевое имя каталога и путевое имя исполняемого файла соответственно. Эта информация может быть использована для определения местонахождения файлов изображений или других данных программы.
Помимо драйверов доступа к Microsoft SQL Server, MySQL, Oracle, PostgreSQL, Sybase Adaptive Server и ODBC SQL-модуль теперь включает драйвер IBM DB2 (под названием QDB2).
Класс QSqlError теперь содержит метод showMessage(), который с помощью QMessageBox может сообщить об ошибках драйвера и сервера баз данных.
Класс QSqlCursor упрощает вывод содержимого таблицы базы данных и заполнение форм редактирования. В предыдущих версиях Qt для отображения результатов JOIN вам нужно было либо наследовать QSqlCursor, либо создавать вид и привязывать к нему QSqlCursor. Новый класс QSqlSelectCursor предлагает более удобное решение. Он может быть использован для вывода результатов любого SQL-запроса SELECT. По умолчанию класс выводит данные в режиме только для чтения, однако, переопределяя соответствующие виртуальные методы, можно реализовать функции INSERT, UPDATE и DELETE.
Теперь ваши собственные SQL-драйверы можно включить в приложение на этапе сборки, и не компилировать их в виде отдельных плагинов. Для этого вам необходимо известить о вашем драйвере класс QSqlDatabase, так как он получает список доступных драйверов, сканируя каталог SQL-плагинов, и ему ничего не известно об SQL-драйверах, включенных в приложение. Добавление вашего драйвера осуществляется с помощью одной строки:
QSqlDatabase::registerSqlDriver( "MYDRIVER", new
QSqlDriverCreator<MyDriver>());
Теперь MYDRIVER может быть использован точно так же, как и любой другой SQL-плагин Qt.
В Qt 3.1 для поддержки IN-параметров был использован механизм привязки значений. Qt 3.2 распространяет использование этого механизма для поддержки параметров OUT и INOUT. Это может быть особенно полезным при работе с сохраненными процедурами.
QSqlQuery query;
query.prepare("CALL GET_NEXT_SEQ_ID(:table, :seqid)");
query.bindValue(":table", "INVOICES");
query.bindValue(":seqid", 0, QSql::Out);
query.exec();
int sequenceNumber = query.boundValue(":seqid");
Переменная :table используется в качестве IN-параметра (по умолчанию). Также bindValue() поддерживает тип параметра QSql::InOut.
Данные, передаваемые между клиентскими приложениями и сервером баз данных, не шифруются. Для обеспечения безопасности необходима уверенность в том, что сетевой трафик проходит по защищенным каналам. Теперь стало возможным использование защищенных SSL-соединений при работе с базами данных, поддерживающими такие соединения.
Включение шифрования должно быть активизировано перед установкой соединения
с помощью QSqlDatabase::open()
i>.
Вот как вы можете установить безопасное соединение с сервером MySQL:
QSqlDatabase* db = new QSqlDatabase("QMYSQL3");
// Set username, host, password, etc.
db->setConnectOptions("CLIENT_SSL");
if (!db->open()) {
// Fallback to unencrypted connection
db->setConnectOptions("");
db->open();
if (!db->open())
// Cannot connect at all
}
Шифрование включается с помощью опции установки соединения с MySQL CLIENT_SSL. Опции установки соединения очищаются с помощью вызова setConnectOptions(""). К сожалению, эти опции специфичны для каждой базы данных. Например, для установки безопасного соединения с сервером PostgreSQL необходимо использовать совершенно другую опцию:
db->setConnectOptions("requiressl=1");
Несколько параметров должны быть разделены точкой с запятой. Вот пример того, как для установки соединения с сервером MySQL использовать одновременно шифрование и компрессию:
db->setConnectOptions("CLIENT_SSL;CLIENT_COMPRESS");
Обзор доступных опций установки соединения приводится в документации класса QSqlDatabase.