├── Image └── tableview.png ├── LICENSE ├── ListView ├── ListView.pro ├── QmlListModel.qml ├── main.cpp ├── main.qml └── qml.qrc ├── QmlModelView.pro ├── README.md └── TableView ├── EasyTableModel.cpp ├── EasyTableModel.h ├── EasyTableWidget.qml ├── TableView.pro ├── main.cpp ├── main.qml └── qml.qrc /Image/tableview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gongjianbo/QmlModelView/9ce0c8879682f2911f80562dd1876ab548e275dd/Image/tableview.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 龚建波 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ListView/ListView.pro: -------------------------------------------------------------------------------- 1 | QT += quick 2 | 3 | CONFIG += c++11 4 | 5 | SOURCES += \ 6 | main.cpp 7 | 8 | RESOURCES += qml.qrc 9 | -------------------------------------------------------------------------------- /ListView/QmlListModel.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.12 3 | import QtQuick.Layouts 1.12 4 | 5 | Item { 6 | id: control 7 | 8 | //几个简单的ListView应用展示 9 | RowLayout{ 10 | anchors.fill: parent 11 | spacing: 10 12 | 13 | ListView{ 14 | id: listview_1 15 | Layout.fillHeight: true 16 | Layout.fillWidth: true 17 | 18 | orientation: ListView.Vertical 19 | clip: true 20 | spacing: 2 21 | model: 20 //用数字类似于Repeater 22 | delegate: Rectangle{ 23 | width: ListView.view.width 24 | height: 30 25 | radius: 15 26 | //附加属性见文档,注意只对delegate第一层的Item 27 | color: ListView.isCurrentItem?"darkRed":"red" 28 | Text { 29 | anchors.centerIn: parent 30 | text: index+1 31 | } 32 | MouseArea{ 33 | anchors.fill: parent 34 | onClicked: listview_1.currentIndex=index 35 | } 36 | } 37 | //highlight感觉没啥用,只能做个背景 38 | highlight: Rectangle{ 39 | width: ListView.view.width 40 | height: 30 41 | color: "darkRed" 42 | } 43 | 44 | //有焦点才能按键切换当前item 45 | //经测试还得给外面的Loader加focus 46 | focus: true 47 | keyNavigationEnabled: true 48 | keyNavigationWraps: true //打到最后一个返回到第一个 49 | 50 | //默认不显示滚动条,我们用一个最简单的滚动条 51 | ScrollBar.vertical: ScrollBar{} 52 | } 53 | 54 | ListView{ 55 | id: listview_2 56 | Layout.fillHeight: true 57 | Layout.fillWidth: true 58 | 59 | clip: true 60 | spacing: 2 61 | model: ["a","b","c","d","e","f","g","h","i","j","k","l","m","n"] //可以用Json数组 62 | delegate: Rectangle{ 63 | width: ListView.view.width 64 | height: 30 65 | color: "green" 66 | Text { 67 | anchors.centerIn: parent 68 | text: modelData 69 | } 70 | } 71 | //不要拉扯的动画 72 | boundsBehavior: Flickable.StopAtBounds 73 | //header固定在顶部 74 | headerPositioning: ListView.OverlayHeader 75 | header: Rectangle{ 76 | width: ListView.view.width 77 | height: 30 78 | color: "darkGreen" 79 | z:2 //默认会被内容遮挡住 80 | } 81 | 82 | //footer固定在底部 83 | footerPositioning: ListView.OverlayFooter 84 | footer: Rectangle{ 85 | width: ListView.view.width 86 | height: 30 87 | color: "darkGreen" 88 | z:2 89 | } 90 | ScrollBar.vertical: ScrollBar{} 91 | } 92 | 93 | ListView{ 94 | id: listview_3 95 | Layout.fillHeight: true 96 | Layout.fillWidth: true 97 | 98 | clip: true 99 | spacing: 2 100 | model: [ 101 | {"name":"tom","age":10}, 102 | {"name":"sen","age":15}, 103 | {"name":"kin","age":13}, 104 | {"name":"li","age":18} 105 | ] 106 | delegate: Rectangle{ 107 | width: ListView.view.width 108 | height: 30 109 | color: "blue" 110 | Text { 111 | anchors.centerIn: parent 112 | text: modelData.name+":"+modelData.age 113 | } 114 | } 115 | 116 | boundsBehavior: Flickable.StopAtBounds 117 | ScrollBar.vertical: ScrollBar{} 118 | } 119 | 120 | ListView{ 121 | id: listview_4 122 | Layout.fillHeight: true 123 | Layout.fillWidth: true 124 | 125 | //listview默认只有竖向滚动条,要显示横向的需要加上下面两句 126 | flickableDirection: Flickable.AutoFlickIfNeeded 127 | contentWidth: width*2 128 | 129 | clip: true 130 | spacing: 2 131 | model: ListModel{ 132 | ListElement{ name:"一"; age:"1" } 133 | ListElement{ name:"切"; age:"2" } 134 | ListElement{ name:"都"; age:"3" } 135 | ListElement{ name:"是"; age:"4" } 136 | ListElement{ name:"稍"; age:"5" } 137 | ListElement{ name:"纵"; age:"6" } 138 | ListElement{ name:"即"; age:"7" } 139 | ListElement{ name:"逝"; age:"8" } 140 | ListElement{ name:"的"; age:"9" } 141 | ListElement{ name:"追"; age:"10" } 142 | ListElement{ name:"寻"; age:"11" } 143 | } 144 | 145 | delegate: Rectangle{ 146 | width: ListView.view.width 147 | height: 30 148 | color: "orange" 149 | Text { 150 | anchors.centerIn: parent 151 | //注意,和直接使用json不一样,不需要modelData 152 | text: name+":"+age 153 | } 154 | } 155 | 156 | boundsBehavior: Flickable.StopAtBounds 157 | ScrollBar.vertical: ScrollBar{} 158 | ScrollBar.horizontal: ScrollBar{} 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /ListView/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 7 | 8 | QGuiApplication app(argc, argv); 9 | 10 | QQmlApplicationEngine engine; 11 | 12 | //qmlRegisterType("EasyModel",1,0,"EasyTableModel"); 13 | 14 | const QUrl url(QStringLiteral("qrc:/main.qml")); 15 | QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, 16 | &app, [url](QObject *obj, const QUrl &objUrl) { 17 | if (!obj && url == objUrl) 18 | QCoreApplication::exit(-1); 19 | }, Qt::QueuedConnection); 20 | engine.load(url); 21 | 22 | return app.exec(); 23 | } 24 | -------------------------------------------------------------------------------- /ListView/main.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Window 2.12 3 | import QtQuick.Controls 2.12 4 | 5 | ApplicationWindow { 6 | id: root_window 7 | visible: true 8 | width: 640 9 | height: 480 10 | title: qsTr("ListView") + root_loader.source 11 | 12 | Loader{ 13 | id: root_loader 14 | anchors.fill: parent 15 | anchors.margins: 10 16 | source: "qrc:/QmlListModel.qml" 17 | focus: true 18 | } 19 | 20 | menuBar: MenuBar { 21 | Menu { 22 | title: qsTr("page") 23 | Action { 24 | text: "QmlListModel" 25 | onTriggered: root_loader.setSource("qrc:/QmlListModel.qml") 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ListView/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | QmlListModel.qml 5 | 6 | 7 | -------------------------------------------------------------------------------- /QmlModelView.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | CONFIG += ordered 3 | 4 | SUBDIRS += ListView TableView 5 | 6 | OTHER_FILES += LICENSE \ 7 | README.md \ 8 | Image/tableview.png 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### QmlModelView 2 | 3 | Example of QML Model-View Based on Qt5.12. 4 | 5 | QML中的Model-View使用示例,以5.12为基础版本。 6 | 7 | --- 8 | **Demo Show(展示):** 9 | 10 | ![2020-02-07](Image/tableview.png) 11 | -------------------------------------------------------------------------------- /TableView/EasyTableModel.cpp: -------------------------------------------------------------------------------- 1 | #include "EasyTableModel.h" 2 | 3 | #include 4 | 5 | EasyTableModel::EasyTableModel(QObject *parent) 6 | : QAbstractTableModel(parent) 7 | { 8 | } 9 | 10 | QStringList EasyTableModel::getHorHeader() const 11 | { 12 | return _horHeaderList; 13 | } 14 | 15 | void EasyTableModel::setHorHeader(const QStringList &header) 16 | { 17 | _horHeaderList=header; 18 | emit horHeaderChanged(); 19 | } 20 | 21 | QJsonArray EasyTableModel::getInitData() const 22 | { 23 | return _initData; 24 | } 25 | 26 | void EasyTableModel::setInitData(const QJsonArray &jsonArr) 27 | { 28 | _initData=jsonArr; 29 | if(_completed){ 30 | loadData(_initData); 31 | } 32 | emit initDataChanged(); 33 | } 34 | 35 | void EasyTableModel::classBegin() 36 | { 37 | //qDebug()<<"EasyTableModel::classBegin()"; 38 | } 39 | 40 | void EasyTableModel::componentComplete() 41 | { 42 | //qDebug()<<"EasyTableModel::componentComplete()"; 43 | _completed=true; 44 | if(!_initData.isEmpty()){ 45 | loadData(_initData); 46 | } 47 | } 48 | 49 | QHash EasyTableModel::roleNames() const 50 | { 51 | //value表示取值,edit表示编辑 52 | return QHash{ 53 | { Qt::DisplayRole,"value" }, 54 | { Qt::EditRole,"edit" } 55 | }; 56 | } 57 | 58 | QVariant EasyTableModel::headerData(int section, Qt::Orientation orientation, int role) const 59 | { 60 | //返回表头数据,无效的返回None 61 | if(role==Qt::DisplayRole){ 62 | if(orientation==Qt::Horizontal){ 63 | return _horHeaderList.value(section,QString::number(section)); 64 | }else if(orientation==Qt::Vertical){ 65 | return QString::number(section); 66 | } 67 | } 68 | return QVariant(); 69 | } 70 | 71 | bool EasyTableModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) 72 | { 73 | if (value != headerData(section, orientation, role)) { 74 | if(orientation==Qt::Horizontal&&role==Qt::EditRole){ 75 | _horHeaderList[section]=value.toString(); 76 | emit headerDataChanged(orientation, section, section); 77 | return true; 78 | } 79 | } 80 | return false; 81 | } 82 | 83 | 84 | int EasyTableModel::rowCount(const QModelIndex &parent) const 85 | { 86 | if (parent.isValid()) 87 | return 0; 88 | return _modelData.count(); 89 | } 90 | 91 | int EasyTableModel::columnCount(const QModelIndex &parent) const 92 | { 93 | if (parent.isValid()) 94 | return 0; 95 | return _horHeaderList.count(); 96 | } 97 | 98 | QVariant EasyTableModel::data(const QModelIndex &index, int role) const 99 | { 100 | if (!index.isValid()) 101 | return QVariant(); 102 | switch (role) { 103 | case Qt::DisplayRole: 104 | case Qt::EditRole: 105 | return _modelData.at(index.row()).at(index.column()); 106 | default: 107 | break; 108 | } 109 | return QVariant(); 110 | } 111 | 112 | bool EasyTableModel::setData(const QModelIndex &index, const QVariant &value, int role) 113 | { 114 | if (value.isValid()&&index.isValid()&&(data(index, role) != value)) { 115 | if(Qt::EditRole==role){ 116 | _modelData[index.row()][index.column()]=value; 117 | emit dataChanged(index, index, QVector() << role); 118 | return true; 119 | } 120 | } 121 | return false; 122 | } 123 | 124 | Qt::ItemFlags EasyTableModel::flags(const QModelIndex &index) const 125 | { 126 | if (!index.isValid()) 127 | return Qt::NoItemFlags; 128 | return Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsEditable; 129 | } 130 | 131 | void EasyTableModel::loadData(const QJsonArray &data) 132 | { 133 | //如果要区分类型的话,可以用role, 134 | //这样ui中就能使用model.role来获取对应index的参数 135 | QVector> newData; 136 | QJsonArray::const_iterator iter; 137 | for(iter=data.begin();iter!=data.end();++iter){ 138 | QVector newRow; 139 | const QJsonObject itemRow=(*iter).toObject(); 140 | newRow.append(itemRow.value("id")); 141 | newRow.append(itemRow.value("name")); 142 | newRow.append(itemRow.value("age")); 143 | newRow.append(itemRow.value("note")); 144 | newData.append(newRow); 145 | } 146 | 147 | emit beginResetModel(); 148 | _modelData=newData; 149 | emit endResetModel(); 150 | } 151 | 152 | /* 153 | bool EasyTableModel::insertRows(int row, int count, const QModelIndex &parent) 154 | { 155 | beginInsertRows(parent, row, row + count - 1); 156 | // FIXME: Implement me! 157 | endInsertRows(); 158 | } 159 | 160 | bool EasyTableModel::insertColumns(int column, int count, const QModelIndex &parent) 161 | { 162 | beginInsertColumns(parent, column, column + count - 1); 163 | // FIXME: Implement me! 164 | endInsertColumns(); 165 | } 166 | 167 | bool EasyTableModel::removeRows(int row, int count, const QModelIndex &parent) 168 | { 169 | beginRemoveRows(parent, row, row + count - 1); 170 | // FIXME: Implement me! 171 | endRemoveRows(); 172 | } 173 | 174 | bool EasyTableModel::removeColumns(int column, int count, const QModelIndex &parent) 175 | { 176 | beginRemoveColumns(parent, column, column + count - 1); 177 | // FIXME: Implement me! 178 | endRemoveColumns(); 179 | }*/ 180 | -------------------------------------------------------------------------------- /TableView/EasyTableModel.h: -------------------------------------------------------------------------------- 1 | #ifndef EASYTABLEMODEL_H 2 | #define EASYTABLEMODEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | //tableview的简易model 13 | class EasyTableModel : public QAbstractTableModel, public QQmlParserStatus 14 | { 15 | Q_OBJECT 16 | Q_INTERFACES(QQmlParserStatus) 17 | Q_PROPERTY(QStringList horHeader READ getHorHeader WRITE setHorHeader NOTIFY horHeaderChanged) 18 | Q_PROPERTY(QJsonArray initData READ getInitData WRITE setInitData NOTIFY initDataChanged) 19 | 20 | public: 21 | explicit EasyTableModel(QObject *parent = nullptr); 22 | 23 | QStringList getHorHeader() const; 24 | void setHorHeader(const QStringList &header); 25 | 26 | QJsonArray getInitData() const; 27 | void setInitData(const QJsonArray &jsonArr); 28 | 29 | // QQmlParserStatus:构造前 30 | void classBegin() override; 31 | // QQmlParserStatus:构造后 32 | void componentComplete() override; 33 | // 自定义role 34 | QHash roleNames() const override; 35 | 36 | // 表头 37 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; 38 | bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override; 39 | 40 | // 数据,这三个必须实现 41 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 42 | int columnCount(const QModelIndex &parent = QModelIndex()) const override; 43 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 44 | 45 | // 编辑 46 | bool setData(const QModelIndex &index, const QVariant &value, 47 | int role = Qt::EditRole) override; 48 | Qt::ItemFlags flags(const QModelIndex& index) const override; 49 | 50 | // Add data: 51 | //bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; 52 | //bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override; 53 | 54 | // Remove data: 55 | //bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; 56 | //bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override; 57 | 58 | private: 59 | void loadData(const QJsonArray &data); 60 | 61 | signals: 62 | void horHeaderChanged(); 63 | void initDataChanged(); 64 | 65 | private: 66 | // 组件是否初始化完成 67 | bool _completed=false; 68 | // 加载的数据 69 | QJsonArray _initData; 70 | // 数据,我一般纯展示,用vector就行了 71 | QVector> _modelData; 72 | // 横项表头 73 | QList _horHeaderList; 74 | }; 75 | 76 | #endif // EASYTABLEMODEL_H 77 | -------------------------------------------------------------------------------- /TableView/EasyTableWidget.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.12 3 | import EasyModel 1.0 4 | 5 | //自定义QtQuick 2中的TableView 6 | Item { 7 | id: control 8 | implicitHeight: 300 9 | implicitWidth: 500 10 | 11 | //行表头-竖向的 12 | property int verHeaderHeight: 30 13 | property int verHeaderWidth: 30 14 | //列表头-横向的 15 | property int horHeaderHeight: 30 16 | //property int horHeaderWidth: 30 17 | //滚动条 18 | property color scrollBarColor: "cyan" 19 | property int scrollBarWidth: 6 20 | //列宽 21 | property variant columnWidthArr: [100,100,100,200] 22 | 23 | EasyTableModel{ 24 | id: table_model 25 | horHeader: ["Id","Name","Age","Note"] 26 | initData: [ 27 | {"id":1,"name":"gonge","age":20,"note":"test model view"}, 28 | {"id":2,"name":"gonge","age":21,"note":"test model view"}, 29 | {"id":3,"name":"gonge","age":22,"note":"test model view"}, 30 | {"id":4,"name":"gonge","age":23,"note":"test model view"}, 31 | {"id":5,"name":"gonge","age":24,"note":"test model view"}, 32 | {"id":6,"name":"gonge","age":25,"note":"test model view"}, 33 | {"id":7,"name":"gonge","age":26,"note":"test model view"}, 34 | {"id":8,"name":"gonge","age":27,"note":"test model view"} 35 | ] 36 | } 37 | 38 | //表格内容(不包含表头) 39 | TableView{ 40 | id: table_view 41 | anchors{ 42 | fill: parent 43 | leftMargin: control.verHeaderWidth 44 | topMargin: control.horHeaderHeight 45 | } 46 | 47 | clip: true 48 | boundsBehavior: Flickable.StopAtBounds 49 | columnSpacing: 1 50 | rowSpacing: 1 51 | //视图的高度 52 | //contentHeight: rowHeightProvider(0) * rows + rowHeightProvider(rows-1) 53 | //视图的宽度 54 | //contentWidth: 55 | //content内容区域边距,但是不影响滚动条的位置 56 | //leftMargin: 57 | //topMargin: 58 | //此属性可以包含一个函数,该函数返回模型中每行的行高 59 | rowHeightProvider: function (row) { 60 | return control.verHeaderHeight; 61 | } 62 | //此属性可以保存一个函数,该函数返回模型中每个列的列宽 63 | columnWidthProvider: function (column) { 64 | return control.columnWidthArr[column]; 65 | //return Math.max(1, (table_view.width - leftMargin) / table_view.columns) 66 | } 67 | ScrollBar.vertical: ScrollBar { 68 | id: scroll_vertical 69 | anchors.right: parent.right 70 | anchors.rightMargin: 2 71 | //active: table_view.ScrollBar.vertical.active 72 | //policy: ScrollBar.AsNeeded 73 | contentItem: Rectangle{ 74 | visible: (scroll_vertical.size<1.0) 75 | implicitWidth: control.scrollBarWidth 76 | color: control.scrollBarColor 77 | } 78 | } 79 | 80 | ScrollBar.horizontal: ScrollBar { 81 | id: scroll_horizontal 82 | anchors.bottom: parent.bottom 83 | anchors.bottomMargin: 2 84 | //active: table_view.ScrollBar.vertical.active 85 | //policy: ScrollBar.AsNeeded 86 | contentItem: Rectangle{ 87 | visible: (scroll_horizontal.size<1.0) 88 | implicitHeight: control.scrollBarWidth 89 | color: control.scrollBarColor 90 | } 91 | } 92 | //model是在C++中定义的,和QtC++是类似的 93 | model: table_model 94 | delegate: Rectangle{ 95 | color: (model.row%2)?"orange":Qt.darker("orange") 96 | TextInput{ 97 | anchors.fill: parent 98 | verticalAlignment: Text.AlignVCenter 99 | horizontalAlignment: Text.AlignHCenter 100 | //elide: Text.ElideRight 101 | selectByMouse: true 102 | selectedTextColor: "black" 103 | selectionColor: "white" 104 | 105 | //获取单元格对应的值 106 | text: model.value 107 | onEditingFinished: { 108 | model.edit=text; 109 | console.log("edit",model.value) 110 | } 111 | } 112 | } 113 | } 114 | 115 | //横项表头 116 | Item{ 117 | id: header_horizontal 118 | anchors{ 119 | left: parent.left 120 | right: parent.right 121 | leftMargin: control.verHeaderWidth 122 | } 123 | height: control.horHeaderHeight 124 | z: 2 125 | //暂存鼠标拖动的位置 126 | property int posXTemp: 0 127 | MouseArea{ 128 | anchors.fill: parent 129 | onPressed: header_horizontal.posXTemp=mouseX; 130 | onPositionChanged: { 131 | if(table_view.contentX+(header_horizontal.posXTemp-mouseX)>0){ 132 | table_view.contentX+=(header_horizontal.posXTemp-mouseX); 133 | }else{ 134 | table_view.contentX=0; 135 | } 136 | header_horizontal.posXTemp=mouseX; 137 | } 138 | } 139 | Row { 140 | id: header_horizontal_row 141 | anchors.fill: parent 142 | leftPadding: -table_view.contentX 143 | clip: true 144 | spacing: 0 145 | 146 | Repeater { 147 | model: table_view.columns > 0 ? table_view.columns : 0 148 | 149 | Rectangle { 150 | id: header_horizontal_item 151 | width: table_view.columnWidthProvider(index)+table_view.columnSpacing 152 | height: control.horHeaderHeight 153 | color: "purple" 154 | 155 | Text { 156 | anchors.centerIn: parent 157 | text: table_model.headerData(index, Qt.Horizontal) 158 | } 159 | Rectangle{ 160 | width: 1 161 | height: parent.height 162 | anchors.right: parent.right 163 | color: "black" 164 | opacity: 0.5 165 | } 166 | MouseArea{ 167 | width: 3 168 | height: parent.height 169 | anchors.right: parent.right 170 | cursorShape: Qt.SplitHCursor 171 | onPressed: header_horizontal.posXTemp=mouseX; 172 | onPositionChanged: { 173 | if((header_horizontal_item.width-(header_horizontal.posXTemp-mouseX))>10){ 174 | header_horizontal_item.width-=(header_horizontal.posXTemp-mouseX); 175 | }else{ 176 | header_horizontal_item.width=10; 177 | } 178 | header_horizontal.posXTemp=mouseX; 179 | control.columnWidthArr[index]=(header_horizontal_item.width-table_view.columnSpacing); 180 | //刷新布局,这样宽度才会改变 181 | table_view.forceLayout(); 182 | } 183 | } 184 | } 185 | } 186 | } 187 | } 188 | 189 | //竖向表头 190 | Column { 191 | id: header_verical 192 | anchors{ 193 | top: parent.top 194 | bottom: parent.bottom 195 | topMargin: control.horHeaderHeight 196 | } 197 | topPadding: -table_view.contentY 198 | z: 2 199 | clip: true 200 | spacing: 1 201 | Repeater { 202 | model: table_view.rows > 0 ? table_view.rows : 0 203 | Rectangle { 204 | width: control.verHeaderWidth 205 | height: table_view.rowHeightProvider(index) 206 | color: "green" 207 | Text { 208 | anchors.centerIn: parent 209 | text: table_model.headerData(index, Qt.Vertical) 210 | } 211 | } 212 | } 213 | } 214 | 215 | } 216 | -------------------------------------------------------------------------------- /TableView/TableView.pro: -------------------------------------------------------------------------------- 1 | QT += quick 2 | 3 | CONFIG += c++11 4 | 5 | RESOURCES += qml.qrc 6 | 7 | SOURCES += \ 8 | EasyTableModel.cpp \ 9 | main.cpp 10 | 11 | HEADERS += \ 12 | EasyTableModel.h 13 | -------------------------------------------------------------------------------- /TableView/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "EasyTableModel.h" 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 9 | 10 | QGuiApplication app(argc, argv); 11 | 12 | QQmlApplicationEngine engine; 13 | 14 | qmlRegisterType("EasyModel",1,0,"EasyTableModel"); 15 | 16 | const QUrl url(QStringLiteral("qrc:/main.qml")); 17 | QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, 18 | &app, [url](QObject *obj, const QUrl &objUrl) { 19 | if (!obj && url == objUrl) 20 | QCoreApplication::exit(-1); 21 | }, Qt::QueuedConnection); 22 | engine.load(url); 23 | 24 | return app.exec(); 25 | } 26 | -------------------------------------------------------------------------------- /TableView/main.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Window 2.12 3 | 4 | Window { 5 | visible: true 6 | width: 640 7 | height: 480 8 | title: qsTr("TableView") 9 | 10 | Rectangle{ 11 | anchors.fill: parent 12 | anchors.margins: 20 13 | color: "gray" 14 | 15 | EasyTableWidget{ 16 | anchors.fill: parent 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /TableView/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | EasyTableWidget.qml 5 | 6 | 7 | --------------------------------------------------------------------------------