qt5.9之QSqlRelationaITableModel實例用法

普通界面佈局:

理論解析:

         QSqlRelationalTableModel 是 QSqITableModel 的子類。QSqlRelationalTableModel 可以處理關係數據表,所謂關係數據表, 是指將主表裏的某個字段存儲爲代碼型字段,而代碼的具體意義在另外一個數據表裏。

        有關數據庫對應的知識點,與工程使用的db文件,在工程項目裏面,請自己查看,例子在最後有鏈接:

工程文件:

QT       += sql

對應主文件的頭文件:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include    <QLabel>
#include    <QString>

#include    <QtSql>
#include    <QDataWidgetMapper>

//#include    "qwcomboboxdelegate.h"


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

private:
    QSqlDatabase  DB; //數據庫連接

    QSqlRelationalTableModel  *tabModel;//數據模型

    QItemSelectionModel *theSelection;//選擇模型

    void    openTable();//打開數據表
//    void    getFieldNames();//獲取字段名稱
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_currentChanged(const QModelIndex &current, const QModelIndex &previous);

// QTableView的SelectionModel的行發生了變化,進行處理
//    void on_currentRowChanged(const QModelIndex &current, const QModelIndex &previous);
///////////////////////
    void on_actOpenDB_triggered();

    void on_actRecAppend_triggered();

    void on_actRecInsert_triggered();

    void on_actRevert_triggered();

    void on_actSubmit_triggered();

    void on_actRecDelete_triggered();

    void on_actFields_triggered();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

首先是主程序部分:

初始化函數:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    this->setCentralWidget(ui->tableView);

    ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);
    ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableView->setAlternatingRowColors(true);
    //    ui->tableView->resizeColumnsToContents();
    //    ui->tableView->horizontalHeader()->setStretchLastSection(true);
}

這裏沒有什麼好說的啦,然後是常規的打開文件,就是打開數據庫了:

void MainWindow::on_actOpenDB_triggered()
{
    QString aFile=QFileDialog::getOpenFileName(this,"選擇數據庫文件","",
                             "SQL Lite數據庫(*.db *.db3)");
    if (aFile.isEmpty())
       return;

//打開數據庫
    DB=QSqlDatabase::addDatabase("QSQLITE"); //添加 SQL LITE數據庫驅動
    DB.setDatabaseName(aFile); //設置數據庫名稱
//    DB.setHostName();
//    DB.setUserName();
//    DB.setPassword();
    if (!DB.open())   //打開數據庫
    {
        QMessageBox::warning(this, "錯誤", "打開數據庫失敗",
                                 QMessageBox::Ok,QMessageBox::NoButton);
        return;
    }

//打開數據表
    openTable();
}

打開數據表中的數據:

void MainWindow::openTable()
{//打開數據表
    tabModel=new QSqlRelationalTableModel(this,DB);
    tabModel->setTable("studInfo"); //設置數據表
    tabModel->setEditStrategy(QSqlTableModel::OnManualSubmit);  //OnManualSubmit , OnRowChange
    tabModel->setSort(0,Qt::AscendingOrder);

    tabModel->setHeaderData(0,Qt::Horizontal,"學號");
    tabModel->setHeaderData(1,Qt::Horizontal,"姓名");
    tabModel->setHeaderData(2,Qt::Horizontal,"性別");
    tabModel->setHeaderData(3,Qt::Horizontal,"學院");
    tabModel->setHeaderData(4,Qt::Horizontal,"專業");

    //設置代碼字段的查詢關係數據表
    tabModel->setRelation(3,QSqlRelation("departments","departID","department")); //學院
    tabModel->setRelation(4,QSqlRelation("majors","majorID","major"));//專業

    theSelection=new QItemSelectionModel(tabModel);
    connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),
            this,SLOT(on_currentChanged(QModelIndex,QModelIndex)));

    ui->tableView->setModel(tabModel);
    ui->tableView->setSelectionModel(theSelection);
    ui->tableView->setItemDelegate(new QSqlRelationalDelegate(ui->tableView)); //爲關係型字段設置缺省代理組件

    tabModel->select(); //打開數據表

//    ui->tableView->resizeColumnsToContents();
//    ui->tableView->horizontalHeader()->setStretchLastSection(true);

    ui->actOpenDB->setEnabled(false);
    ui->actRecAppend->setEnabled(true);
    ui->actRecInsert->setEnabled(true);
    ui->actRecDelete->setEnabled(true);
    ui->actFields->setEnabled(true);
}

    QSqlRelationalTableModel 類的主要函數與 QSqlTableModel 相同, 有一個新的函數 setRelation() 用於設置代碼字段的關聯數據表和l關聯字段。

openTable()函數中還有關鍵的一行 :

ui->tableView->setItemDelegate(new QSqlRelationalDelegate(ui->tableView)); //爲關係型字段設置缺省代理組件

       這是在 tableView 中爲代碼字段創建缺省的關係型代理組件,這樣在 tableView 中編輯代碼字段的內容時,纔會出現一個下拉列表框,列出代碼表的所有可選內容。

void MainWindow::on_currentChanged(const QModelIndex &current, const QModelIndex &previous)
{//更新actPost和actCancel 的狀態
    Q_UNUSED(current);
    Q_UNUSED(previous);
    ui->actSubmit->setEnabled(tabModel->isDirty()); //有未保存修改時可用
    ui->actRevert->setEnabled(tabModel->isDirty());
}

獲取字段列表:

void MainWindow::on_actFields_triggered()
{//獲取字段列表
    QSqlRecord  emptyRec=tabModel->record();//獲取空記錄,只有字段名
    QString  str;
    for (int i=0;i<emptyRec.count();i++)
        str=str+emptyRec.fieldName(i)+'\n';

    QMessageBox::information(this, "所有字段名", str,
                             QMessageBox::Ok,QMessageBox::NoButton);
}

添加記錄:

void MainWindow::on_actRecAppend_triggered()
{//添加記錄
    tabModel->insertRow(tabModel->rowCount(),QModelIndex()); //在末尾添加一個記錄
    QModelIndex curIndex=tabModel->index(tabModel->rowCount()-1,1);//創建最後一行的ModelIndex
    theSelection->clearSelection();//清空選擇項
    theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);//設置剛插入的行爲當前選擇行
//    int currow=curIndex.row(); //獲得當前行
//    tabModel->setData(tabModel->index(currow,0),2000+tabModel->rowCount()); //設置字段缺省值
//    tabModel->setData(tabModel->index(currow,2),"男");
}

插入記錄:

void MainWindow::on_actRecInsert_triggered()
{//插入記錄
    QModelIndex curIndex=ui->tableView->currentIndex();
    tabModel->insertRow(curIndex.row(),QModelIndex());

    theSelection->clearSelection();//清除已有選擇
    theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);
}

修改記錄:

void MainWindow::on_actRevert_triggered()
{//取消修改
    tabModel->revertAll();
    ui->actSubmit->setEnabled(false);
    ui->actRevert->setEnabled(false);
}

保存修改:

void MainWindow::on_actSubmit_triggered()
{//保存修改
    bool res=tabModel->submitAll();
    if (!res)
        QMessageBox::information(this, "消息", "數據保存錯誤,錯誤信息\n"+tabModel->lastError().text(),
                                 QMessageBox::Ok,QMessageBox::NoButton);
    else
    {
        ui->actSubmit->setEnabled(false);
        ui->actRevert->setEnabled(false);
    }
}

刪除當前記錄:

void MainWindow::on_actRecDelete_triggered()
{//刪除當前記錄
    tabModel->removeRow(theSelection->currentIndex().row());

//    QModelIndex curIndex=theSelection->currentIndex();//獲取當前選擇單元格的模型索引
//    if (curIndex.row()==tabModel->rowCount()-1)//最後一行
//        tabModel->removeRow(curIndex.row()); //刪除最後一行
//    else
//    {
//        tabModel->removeRow(curIndex.row());//刪除一行,並重新設置當前選擇行
//        theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);
//    }

    tabModel->submitAll(); //立即更新
}

鏈接:https://pan.baidu.com/s/1QNr8dl5Ocuf4VP1m9jRQfA 
提取碼:rgot

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章