KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Жасмин Бланшет - QT 4: программирование GUI на С++

Жасмин Бланшет - QT 4: программирование GUI на С++

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Жасмин Бланшет, "QT 4: программирование GUI на С++" бесплатно, без регистрации.
Перейти на страницу:

Ниже приводится пример использования QSqlTableModel для выполнения команды SELECT:

QSqlTableModel model;

model.setTable("cd");

model.setFilter("year >= 1998");

model.select();

Это эквивалентно запросу

SELECT * FROM cd WHERE year >= 1998

Просмотр результирующего набора выполняется путем получения заданной записи функцией QSqlTableModel::record() и доступа к отдельным полям с помощью функции value():

for (int i = 0; i < model.rowCount(); ++i) {

QSqlRecord record = model.record(i);

QString title = record.value("title").toString();

int year = record.value("year").toInt();

cerr << qPrintable(title) << ": " << year << endl;

}

Функция QSqlRecord::value() принимает либо имя поля, либо индекс поля. При работе с большими наборами данных рекомендуется задавать поля с помощью их индексов. Например:

int titleIndex = model.record().indexOf("title");

int yearIndex = model.record().indexOf("year");

for (int i = 0; i < model.rowCount(); ++i) {

QSqlRecord record = model.record(i);

QString title = record.value(titleIndex).toString();

int year = record.value(yearIndex).toInt();

cerr << qPrintable(title) << ": " << year << endl;

}

Для вставки записи в таблицу базы данных мы действуем так же, как если бы делали вставку в двумерную модель: сначала вызываем функцию insertRow() для создания новой пустой строки (записи) и затем используем setData() для установки значения каждого столбца (поля записи).

QSqlTableModel model;

model.setTable("cd");

int row = 0;

model.insertRows(row, 1);

model.setData(model.index(row, 0), 113);

model.setData(model.index(row, 1), "Shanghai My Heart");

model.setData(model.index(row, 2), 224);

model.setData(model.index(row, 3), 2003);

model.submitAll();

После вызова submitAll() запись может быть перемещена в другую позицию, зависящую от упорядоченности таблицы. Вызов submitAll() возвратит false, если вставка окажется неудачной.

Важным отличием модели SQL от стандартной модели является необходимость вызова в модели SQL функции submitAll() для записи всех изменений в базу данных

Для обновления записи мы должны сначала установить QSqlTableModel на запись, которую мы хотим модифицировать (например, используя функции select()). Затем мы извлекаем запись, обновляем соответствующие поля и записываем наши изменения обратно в базу данных:

QSqlTableModel model;

model.setTable("cd");

model.setFilter("id = 125");

model.select();

if (model.rowCount() == 1) {

QSqlRecord record = model.record(0);

record.setValue("title", "Melody A.M.");

record.setValue("year", record.value("year").toInt() + 1);

model.setRecord(0, record);

model.submitAll();

}

Если имеется запись, удовлетворяющая заданному фильтру, доступ к ней мы получаем при помощи функции QSqlTableModel::record(). Мы осуществляем наши изменения и вновь записываем в базу данных запись с новыми значениями полей.

Кроме того, обновление можно выполнить при помощи функции setData(), как это делается для модели, отличной от SQL—модели. Для получения доступа к полям записи используются индексы модели с указанием номера строки (записи) и столбца (поля):

model.select();

if (model.rowCount() == 1) {

model.setData(model.index(0, 1), "Melody A.M.");

model.setData(model.index(0, 3),

model.data(model.index(0, 3)).toInt() + 1);

model.submitAll();

}

Удаление записи напоминает ее обновление:

model.setTable("cd");

model.setFilter("id = 125");

model.select();

if (model.rowCount() == 1) {

model.removeRows(0, 1);

model.submitAll();

}

В вызове removeRows() указываются номер строки первой удаляемой записи и количество удаляемых записей. В следующем примере удаляются все записи, удовлетворяющие фильтру:

model.setTable("cd");

model.setFilter("year < 1990");

model.select();

if (model.rowCount() > 0) {

model.removeRows(0, model.rowCount());

model.submitAll();

}

Классы QSqlQuery и QSqlTableModel обеспечивают интерфейс между Qt и базой данных SQL. Используя эти классы, можно создавать формы, представляющие данные пользователям и позволяющие им вставлять, обновлять и удалять записи.

Представление данных в табличной форме

Во многих случаях табличное представление является самым простым представлением набора данных для пользователей. В этом и последующих разделах мы рассмотрим простое приложение CD Collection (Коллекция компакт-дисков), в котором модель QSqlTableModel и ее подкласс QSqlRelationalTableModel используются для просмотра и взаимодействия пользователей с данными, хранимыми в базе данных.

Главная форма показывает представление «master—detail» для компакт-дисков и дорожек текущего компакт-диска (рис. 13.1).

Рис. 13.1. Приложение CD Collection.

В приложении используются три таблицы, определенные следующим образом:

CREATE TABLE artist (

id INTEGER PRIMARY KEY,

name VARCHAR(40) NOT NULL,

country VARCHAR(40));

CREATE TABLE cd (

id INTEGER PRIMARY KEY,

title VARCHAR(40) NOT NULL,

artistid INTEGER NOT NULL,

year INTEGER N0T NULL,

FOREIGN KEY (artistid) REFERENCES artist);

CREATE TABLE track (

id INTEGER PRIMARY KEY,

title VARCHAR(40) NOT NULL,

duration INTEGER NOT NULL,

cdid INTEGER NOT NULL,

FOREIGN KEY (cdid) REFERENCES cd);

Некоторые базы данных не поддерживают внешние ключи. В этом случае мы должны убрать фразы FOREIGN KEY. Пример будет все-таки работать, но база данных не будет поддерживать целостность на уровне ссылок.

Рис. 13.2. Таблицы приложения CD Collection.

В этом разделе мы создадим диалоговое окно, позволяющее пользователю редактировать список артистов, используя простую форму с таблицей. Пользователь может вставлять, обновлять или удалять артистов при помощи кнопок формы. Обновления можно делать напрямую, просто редактируя текст ячеек. Изменения вносятся в базу данных при нажатии пользователем кнопки Enter или при переходе на другую запись.

Рис. 13.3. Диалоговое окно ArtistForm.

Ниже приводится определение класса для диалогового окна ArtistForm:

01 class ArtistForm : public QDialog

02 {

03 Q_OBJECT

04 public:

05 ArtistForm(const QString &name, QWidget *parent = 0);

06 private slots:

07 void addArtist();

08 void deleteArtist();

09 void beforeInsertArtist(QSqlRecord &record);

10 private:

11 enum {

12 Artist_Id = 0,

13 Artist_Name = 1,

14 Artist_Country = 2

15 };

16 QSqlTableModel *model;

17 QTableView *tableView;

18 QPushButton *addButton;

19 QPushButton *deleteButton;

20 QPushButton *closeButton;

21 };

Конструктор этого класса очень похож на конструктор, который использовался бы для создания формы, построенной для модели, отличной от SQL—модели:

01 ArtistForm::ArtistForm(const QString &name, QWidget *parent)

02 : QDialog(parent)

03 {

04 model = new QSqlTableModel(this);

05 model->setTable("artist");

06 model->setSort(Artist_Name, Qt::AscendingOrder);

07 model->setHeaderData(Artist_Name, Qt::Horizontal, tr("Name"));

08 model->setHeaderData(Artist_Country, Qt::Horizontal, tr("Country"));

09 model->select();

10 connect(model, SIGNAL(beforeInsert(QSqlRecord &)),

11 this, SLOT(beforeInsertArtist(QSqlRecord &)));

12 tableView = new QTableView;

13 tableView->setModel(model);

14 tableView->setColumnHidden(Artist_Id, true);

15 tableView->setSelectionBehavior(QAbstractItemView::SelectRows);

16 tableView->resizeColumnsToContents();

17 for (int row = 0; row < model->rowCount(); ++row) {

18 QSqlRecord record = model->record(row);

19 if (record.value(Artist_Name).toString() == name) {

20 tableView->selectRow(row);

21 break;

22 }

23 }

24 …

25 }

Конструктор начинается с создания объекта QSqlTableModel. Мы передаем this в качестве родителя, чтобы владельцем модели стала форма. Нами выбрана сортировка по столбцу 1 (задается константой Artist_Name), который соответствует полю имени. Если бы мы не задали заголовки столбцов, то использовались бы имена полей. Мы предпочитаем их указать, чтобы обеспечить правильный регистр и локализацию.

Затем создается QTableView для визуального отображения модели. Мы не показываем поле id и устанавливаем такую ширину столбцов, которая будет достаточна для размещения в них текста без необходимости вывода многоточия.

Конструктор ArtistForm принимает имя артиста, который будет выбран при выводе на экран диалогового окна. Мы проходим по записям таблицы artist и выбираем этого артиста. Остальная часть программного кода конструктора используется для создания кнопок и подключения к ним слотов, а также для компоновки дочерних виджетов в диалоговом окне.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*