用QtQuick Controls 2 中的TableView构建表格

前言

​ 由于QtQuick Controls 1 里的TableView存在严重的性能问题,且事实上QtQuick Controls 1已经处于废弃状态,在Qt5.12中,QtQuick Controls 2更新了 TableView 组件,但新的TableView现在没有定义表头的接口,需要开发者自己实现,这方面资料比较少。在Qt creator的实例中有几个TableView的示例,但都不是sql数据模型的。这里给出了一种使用QSqlQueryModel作为模型在qml实现表格的方法。

代码有两部分构成,一=是自定义的TableView组件,而是作为model的c++模型,这里继承自QSqlQueryModel

实现

QML
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.12
import com.appSql 1.0			

Item {
    id: root
    property string tableName: "学生表"
    property int verHeaderHeight: 30								
    property int verHeaderWidth: 30									
    property int horHeaderHeight: 30								
    property variant columnWidthArr: [200,100,100,100,100,100]		//定义列宽数组


    TableView {
        id: tableView
        columnSpacing: 1
        columnWidthProvider: function (column) {
            return root.columnWidthArr[column];
        }
        rowHeightProvider: function (row) {
            return root.verHeaderHeight;
        }
        Layout.margins: 15
        anchors{
            fill: parent
            leftMargin: root.verHeaderWidth
            topMargin: root.horHeaderHeight
        }
        model: TableModel{ id: table_model ;m_tableName: tableName}
        clip: true
        delegate: Rectangle {							//这里是定义表格内容
            width: tableView.columnWidthProvider(model.row)
            height: horHeaderHeight
            Label {
                id: label
                text: model.value
                anchors.fill: parent
                anchors.margins: 10
                color: "black"
                font.pixelSize: 15
                verticalAlignment: Text.AlignVCenter
                horizontalAlignment: Text.AlignHCenter
            }
        }

    }
    //定义横向表头
    Item{
        id: header_horizontal
        anchors{
            left: parent.left
            right: parent.right
            leftMargin: root.verHeaderWidth
        }
        height: root.horHeaderHeight
        z: 2

        Row {
            id: header_horizontal_row
            anchors.fill: parent
            leftPadding: -tableView.contentX
            clip: true
            spacing: 0

            Repeater {
                model: tableView.columns > 0 ? tableView.columns : 0

                Rectangle {
                    id: header_horizontal_item
                    width: tableView.columnWidthProvider(index)+tableView.columnSpacing
                    height: root.horHeaderHeight
                    color: "#1C77C3"

                    Text {
                        anchors.centerIn: parent
                        text: table_model.headerData(index, Qt.Horizontal)
                        color: "white"
                    }
                    Rectangle{
                        width: 1
                        height: parent.height
                        anchors.right: parent.right
                        color: "black"
                        opacity: 0.5
                    }
                }
            }
        }
    }
	//定义纵向表头
    Column {
        id: header_verical
        anchors{
            top: parent.top
            bottom: parent.bottom
            topMargin: root.horHeaderHeight
        }
        topPadding: -tableView.contentY
        z: 2
        clip: true
        spacing: 1
        Repeater {
            model: tableView.rows > 0 ? tableView.rows : 0		//返回模型的行数,这里需要覆写rowCount函数
            Rectangle {
                width: root.verHeaderWidth
                height: tableView.rowHeightProvider(index)
                color: "#1C77C3"
                Text {
                    anchors.centerIn: parent
                    text: table_model.headerData(index, Qt.Vertical)
                    color: "white"
                }
            }
        }
    }
    onTableNameChanged: {
        console.log("tablename changed!")
        tableView.forceLayout()
    }

}
c++模型实现
//tablemodel.h
#ifndef TABLEMODEL_H
#define TABLEMODEL_H

#include <QSqlQueryModel>

#include <QSqlQuery>

class tableModel:public QSqlQueryModel
{
    Q_OBJECT
    Q_PROPERTY(QString m_tableName READ tableName WRITE setTableName NOTIFY tableNameChanged)
public:
    tableModel(QSqlQueryModel* parent = nullptr);
    Q_INVOKABLE QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
    QVariant data(const QModelIndex &index, int role) const override;
    QHash<int, QByteArray> roleNames() const override;
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;

    QString tableName() const;
    void setTableName(const QString _tableName);
signals:
    void tableNameChanged();
private:
    QString m_tableName;
    QVector<QString> m_tableTitle;
    QSqlQuery* m_query;
    QHash<int, QByteArray> m_roleNames;
};

#endif // TABLEMODEL_H
//tablemodel.cpp
#include "tablemodel.h"
#include <QDebug>
#include <QSqlDriver>
#include <QSqlError>
#include <QSqlRecord>

tableModel::tableModel(QSqlQueryModel* parent)
    :QSqlQueryModel(parent), m_tableName(""), m_query(new QSqlQuery(QSqlDatabase::database()))
{
    m_roleNames[Qt::DisplayRole] = "value";
    m_roleNames[Qt::EditRole] = "edit";


    qDebug()<<QSqlDatabase::database().connectionNames();

    connect(this, &tableModel::tableNameChanged,
            [&]{
        qDebug()<<"tableNameChanged";
        QString queryser;
        if(m_tableName == "选课表")
        {
             queryser= QString("select "
                               "学生表.学号, 学生表.姓名, 选课表.课程号, 课程表.课程名, 成绩 "
                               "from "
                               "选课表, 学生表, 课程表 "
                               "where "
                               "课程表.课程号 = 选课表.课程号 and 学生表.学号 = 选课表.学号");
             qDebug()<<queryser;
        }
        else{
            queryser = QString("select * from %1").arg(m_tableName);

        }
        if(!m_query->exec(queryser))
            qDebug()<<m_query->lastError();

        this->setQuery(*m_query);

        int columns = this->columnCount();
        m_tableTitle.clear();
        for(int i = 0; i < columns; ++i)
        {
            m_tableTitle.append(m_query->record().fieldName(i));//获取字段名
        }
    });

}

QVariant tableModel::data(const QModelIndex &index, int role) const
{
    QVariant v;
    // the index returns the requested row and column information.
    int row = index.row();
    int column = index.column();

    // boundary check for the row and column
    if(row < 0 || row >= this->rowCount()
            ||column < 0 || column >= this->columnCount())
    {
        return v;
    }
    if (role & ~(Qt::DisplayRole | Qt::EditRole))
        return v;

    qDebug()<<m_query->at();
    qDebug()<<"row :"<<row<<"colum: "<<column<<"role: "<<role;

    m_query->seek(row);
    qDebug()<<m_query->value(column);
    return m_query->value(column);

}

QHash<int, QByteArray> tableModel::roleNames() const
{
    return m_roleNames;
}

QString tableModel::tableName() const
{
    return m_tableName;
}

void tableModel::setTableName(const QString _tableName)
{
    if(_tableName != m_tableName )
    {
        m_tableName = _tableName;
        emit tableNameChanged();
    }

}
QVariant tableModel::headerData(int section, Qt::Orientation orientation, int role) const
{//这个函数获取表头数据
    if(role != Qt::DisplayRole)
        return QVariant();
    if(orientation == Qt::Horizontal)
    {
        return m_tableTitle.at(section);
    }
    else if(orientation == Qt::Vertical)
    {
        return QString::number(section);
    }
    return QVariant();
}
int tableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_query->size();
}
int tableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_query->record().count();
}
posted @ 2020-11-17 22:05  Redwarx008  阅读(1649)  评论(0编辑  收藏  举报