キャッシュされたSQLテーブル
「キャッシュされたテーブル」のサンプルでは、テーブルビューを使用してデータベースにアクセスし、ユーザーがプッシュボタンを使用して明示的に送信するまで、データへの変更をキャッシュする方法を示しています。

このサンプルは、TableEditor という単一のクラスで構成されています。これは、ユーザーがデータベースに格納されたデータを変更できるようにするカスタムダイアログウィジェットです。まず、クラスの定義と使用方法を確認し、その後、実装について見ていきます。
TableEditor クラスの定義
TableEditor クラスはQWidget を継承しており、これによりテーブルエディタウィジェットはトップレベルのダイアログウィンドウとなります。
class TableEditor : public QWidget
{
Q_OBJECT
public:
explicit TableEditor(const QString &tableName, QWidget *parent = nullptr);
private slots:
void submit();
private:
QPushButton *submitButton;
QPushButton *revertButton;
QPushButton *quitButton;
QDialogButtonBox *buttonBox;
QSqlTableModel *model;
};TableEditor のコンストラクタは2つの引数を受け取ります。1つ目は、TableEditor オブジェクトが操作対象とするデータベーステーブルへの参照です。もう1つは親ウィジェットへのポインタであり、これは基底クラスのコンストラクタに渡されます。
QSqlTableModel 変数の宣言に注目してください。この例で後述するように、QSqlTableModel クラスは、QTableView などのビュークラスにデータを提供するために使用できます。QSqlTableModel クラスは、単一のテーブルからデータベースレコードを読み書きすることを可能にする、編集可能なデータモデルを提供します。このクラスは、SQL文の実行や操作を行う手段を提供する、より低レベルのQSqlQuery クラスを基盤として構築されています。
また、ユーザーが明示的に送信を要求するまで、データへの変更をキャッシュするためにテーブルビューをどのように使用できるかについても説明します。そのため、モデルやエディタのボタンに加えて、submit() スロットを宣言する必要があります。
| データベースへの接続 |
|---|
TableEditor クラスを使用する前に、編集したいテーブルが含まれるデータベースへの接続を作成する必要があります:
|
TableEditor クラスの実装
このクラスの実装は、コンストラクタとsubmit() スロットの2つの関数のみで構成されています。コンストラクタ内では、データモデルと各種ウィンドウ要素を作成・カスタマイズします。
TableEditor::TableEditor(const QString &tableName, QWidget *parent)
: QWidget(parent)
{
model = new QSqlTableModel(this);
model->setTable(tableName);
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select();
model->setHeaderData(0, Qt::Horizontal, tr("ID"));
model->setHeaderData(1, Qt::Horizontal, tr("First name"));
model->setHeaderData(2, Qt::Horizontal, tr("Last name"));まず、データモデルを作成し、そのモデルが操作する対象となるSQLデータベーステーブルを設定します。 なお、QSqlTableModel::setTable() 関数はテーブルからデータを選択するものではなく、フィールド情報を取得するだけです。そのため、後でQSqlTableModel::select() 関数を呼び出し、テーブルのデータをモデルに格納します。フィルタやソート条件を指定することで、選択内容をカスタマイズできます(詳細については、QSqlTableModel クラスのドキュメントを参照してください)。
また、モデルの編集戦略も設定します。編集戦略は、ユーザーがビューで行った変更が、いつ実際にデータベースに反映されるかを決定します。ユーザーが明示的に送信するまで、テーブルビュー(つまりモデル内)に変更をキャッシュしておきたいので、QSqlTableModel::OnManualSubmit 戦略を選択します。その他の選択肢としては、QSqlTableModel::OnFieldChange およびQSqlTableModel::OnRowChange があります。
最後に、モデルがQSqlQueryModel クラスから継承しているsetHeaderData()関数を使用して、ビューのヘッダーに表示されるラベルを設定します。
QTableView *view = new QTableView;
view->setModel(model);
view->resizeColumnsToContents();次に、テーブルビューを作成します。QTableView クラスは、テーブルビューのデフォルトのモデル/ビュー実装を提供します。つまり、モデルからの項目を表示するテーブルビューを実装しています。また、ユーザーが項目を編集し、その変更をモデルに保存することも可能です。読み取り専用のビューを作成するには、ビューがQAbstractItemView クラスから継承しているeditTriggers プロパティを使用して、適切なフラグを設定します。
ビューにデータを表示させるには、setModel() 関数を使用して、モデルをビューに渡します。
submitButton = new QPushButton(tr("Submit"));
submitButton->setDefault(true);
revertButton = new QPushButton(tr("&Revert"));
quitButton = new QPushButton(tr("Quit"));
buttonBox = new QDialogButtonBox(Qt::Vertical);
buttonBox->addButton(submitButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(revertButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);TableEditor のボタンは、通常のQPushButton オブジェクトです。これらのボタンをボタンボックスに追加することで、現在のウィジェットスタイルに適したレイアウトでボタンが表示されるようにします。その理由は、ダイアログやメッセージボックスでは通常、そのプラットフォームのインターフェースガイドラインに準拠したレイアウトでボタンが表示されるためです。 当然のことながら、プラットフォームごとにダイアログのレイアウトは異なります。`QDialogButtonBox ` を使用すると、開発者はボタンを追加するだけで、ユーザーのデスクトップ環境に適したレイアウトが自動的に適用されます。
ダイアログのボタンのほとんどは、特定の役割に従います。addButton() 関数を使用してボタンボックスにボタンを追加する際は、QDialogButtonBox::ButtonRole 列挙型を使用してボタンの役割を指定する必要があります。あるいは、QDialogButtonBox には、OK 、Cancel 、Save など、使用可能な標準ボタンがいくつか用意されています。これらはフラグとして存在するため、コンストラクタ内でOR演算を組み合わせることができます。
connect(submitButton, &QPushButton::clicked, this, &TableEditor::submit);
connect(revertButton, &QPushButton::clicked, model, &QSqlTableModel::revertAll);
connect(quitButton, &QPushButton::clicked, this, &TableEditor::close);Quit ボタンをテーブルエディタのclose()スロットに接続し、Submit ボタンをプライベートスロットsubmit() に接続します。後者のスロットがデータトランザクションを処理します。最後に、Revert ボタンをモデルのrevertAll()スロットに接続し、保留中の変更をすべて元に戻します(つまり、元のデータを復元します)。
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addWidget(view);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
setWindowTitle(tr("Cached Table"));
}最後に、ボタンボックスとテーブルビューをレイアウトに追加し、そのレイアウトをテーブルエディタウィジェットに配置して、エディタのウィンドウタイトルを設定します。
void TableEditor::submit()
{
model->database().transaction();
if (model->submitAll()) {
model->database().commit();
} else {
model->database().rollback();
QMessageBox::warning(this, tr("Cached Table"),
tr("The database reported an error: %1")
.arg(model->lastError().text()));
}
}submit() スロットは、ユーザーが変更を保存するために「Submit 」ボタンをクリックするたびに呼び出されます。
まず、QSqlDatabase::transaction() 関数を使用して、データベース上でトランザクションを開始します。データベーストランザクションとは、データベース管理システムや類似のシステムとのやり取りの単位であり、他のトランザクションとは独立して、一貫性があり信頼性の高い方法で処理されます。使用中のデータベースへのポインタは、QSqlTableModel::database() 関数を使用して取得できます。
次に、保留中の変更、つまりモデルで変更された項目をすべて送信しようとします。エラーが発生しなければ、QSqlDatabase::commit() 関数を使用してトランザクションをデータベースにコミットします(一部のデータベースでは、データベース上でアクティブなQSqlQuery がある場合、この関数は機能しないことに注意してください)。 エラーが発生した場合は、QSqlDatabase::rollback() 関数を使用してトランザクションをロールバックし、ユーザーに警告を表示します。
| 関連項目: QtSQLデータベースクラスの完全な一覧、およびモデル/ビュープログラミングのドキュメント。 |
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.