首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >C ++点击按钮后更新QML TableView

C ++点击按钮后更新QML TableView
EN

Stack Overflow用户
提问于 2019-04-22 01:16:27
回答 1查看 0关注 0票数 0

我想通过按下按钮向QML表视图添加一定数量的行。

按下“更新列表模型”后,TableView中将出现一个新行。

我的代码看起来像这样。我想addPerson方法必须发出一个dataChanged事件才能使其正常工作。我怎样才能做到这一点?或者是否有更好的解决方案将QML表视图与C ++模型同步?

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>

#include "MainWindow.h"
int main(int argc, char *argv[]) {
    QGuiApplication app(argc, argv);

    qmlRegisterType<TableModel>("TableModel", 0, 1, "TableModel");

    QQmlApplicationEngine engine;
    MainWindow mainWindow;

    return app.exec();
}

MainWindow.h

#pragma once

#include <QQmlApplicationEngine>
#include <QtQuick>

#include "TableModel.h"

class MainWindow : public QObject {
    Q_OBJECT;

public:
    explicit MainWindow() {
        engine_.load(QUrl(QStringLiteral("qrc:/main.qml")));

        QObject *rootObject = engine_.rootObjects().first();
        QObject::connect(rootObject, SIGNAL(on_ButtonUpdateListModel_click()), this, SLOT(on_ButtonUpdateListModel_click()));
    }

public slots:

    void on_ButtonUpdateListModel_click() {         
        QQuickView view;
        QQmlContext *ctxt = view.rootContext();
        model_.addPerson();
        ctxt->setContextProperty("myModel", &model_);
    }

private:
    TableModel model_;
    QQmlApplicationEngine engine_;
};

TableModel.h

#pragma once

#include <QAbstractTableModel>
#include <QObject>

class TableModel : public QAbstractTableModel {
    Q_OBJECT;
    enum TableRoles { TableDataRole = Qt::UserRole + 1, HeadingRole };

public:
    explicit TableModel(QObject *parent = nullptr) : QAbstractTableModel(parent) {
        table.append({
          "First Name",
          "Last Name",
          "Age",
        });
    }

    int rowCount(const QModelIndex & = QModelIndex()) const override {
        return table.size();
    }

    int columnCount(const QModelIndex & = QModelIndex()) const override {
        return table.at(0).size();
    }

    QVariant data(const QModelIndex &index, int role) const override {
        switch (role) {
        case TableDataRole: {
            return table.at(index.row()).at(index.column());
        }
        case HeadingRole: {
            if (index.row() == 0) {
                return true;
            } else {
                return false;
            }
        }
        default: break;
        }

        return QVariant();
    }

    QHash<int, QByteArray> roleNames() const override {
        QHash<int, QByteArray> roles;
        roles[TableDataRole] = "tabledata";
        roles[HeadingRole] = "heading";
        return roles;
    }

    void addPerson() {
        table.append({
          "Marc",
          "Fonz",
          "25",
        });
        int idx = table.size() - 1;
        emit dataChanged(index(idx), index(idx));
    }

private:
    QVector<QVector<QString>> table;
}; 

main.qml

import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

import Qt.labs.settings 1.0
import Qt.labs.platform 1.0 as Platform

import QtQuick.Controls.Material 2.12
import TableModel 0.1

ApplicationWindow {
    id: window
    visible: true
    width: 1040
    height: 480

    signal on_ButtonUpdateListModel_click()

    ColumnLayout{
        spacing: 2
        anchors.fill: parent
        Button {
            text: qsTr("Update List Model")
            onClicked: on_ButtonUpdateListModel_click()
        }

        TableModel {
            id: myModel
        }
        TableView {
            width: 400
            height: 200
            columnSpacing: 1
            rowSpacing: 1
            clip: true

            ScrollIndicator.horizontal: ScrollIndicator { }
            ScrollIndicator.vertical: ScrollIndicator { }

            model: myModel


            delegate: Rectangle {
                implicitWidth: 100
                implicitHeight: 20
                border.color: "black"
                border.width: 2
                color: (heading==true) ? 'teal':"green"

                TableView.onPooled: console.log(tabledata + " pooled")
                TableView.onReused: console.log(tabledata + " resused")

                Text {
                    text: tabledata
                    font.pointSize: 10
                    anchors.centerIn: parent
                }
            }
        }

    }
}
EN

回答 1

Stack Overflow用户

发布于 2019-04-22 11:05:00

您有以下错误:

  • 在addPerson中你添加了一行,所以你不应该使用dataChanged,因为这个信号表明已经存在的东西被修改了,你应该使用beginInsertRows()和endInsertRows()。
  • 在MainWindow中创建的TableModel与在QML中创建的TableModel不同。
  • 不需要在main.cpp中创建QQmlApplicationEngine,因为只需要使用MainWindow中的那个。
  • 必须将业务逻辑与视图分开,因此将对象从QML导出到C ++被认为是不好的做法。

考虑到上述情况,解决方案是:

  • 使addPerson方法成为Q_INVOKABLE,以便可以在QML中访问它。
  • 使用setContextProperty在启动时将TableModel导出到QML,因此无需注册TableModel。

main.cpp

#include "MainWindow.h"

#include <QGuiApplication>
#include <QQmlApplicationEngine>

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    MainWindow mainwindow;
    return app.exec();
}

TableModel.h

#pragma once

#include <QAbstractTableModel>
#include <QObject>

class TableModel : public QAbstractTableModel {
    Q_OBJECT
    enum TableRoles { TableDataRole = Qt::UserRole + 1, HeadingRole };
public:
    explicit TableModel(QObject *parent = nullptr) : QAbstractTableModel(parent) {
        table.append({
                         "First Name",
                         "Last Name",
                         "Age",
                     });
    }
    int rowCount(const QModelIndex & = QModelIndex()) const override {
        return table.size();
    }

    int columnCount(const QModelIndex & = QModelIndex()) const override {
        return table.at(0).size();
    }

    QVariant data(const QModelIndex &index, int role) const override {
        switch (role) {
        case TableDataRole: {
            return table.at(index.row()).at(index.column());
        }
        case HeadingRole: {
            return index.row() == 0;
        }
        default: break;
        }
        return QVariant();
    }
    QHash<int, QByteArray> roleNames() const override {
        QHash<int, QByteArray> roles;
        roles[TableDataRole] = "tabledata";
        roles[HeadingRole] = "heading";
        return roles;
    }

    Q_INVOKABLE void addPerson() {
        beginInsertRows(QModelIndex(), rowCount(), rowCount());
        table.append({
                         "Marc",
                         "Fonz",
                         "25",
                     });
        endInsertRows();
    }
private:
    QVector<QVector<QString>> table;
};

MainWindow.h

#pragma once

#include <QQmlApplicationEngine>
#include <QQmlContext>

#include "TableModel.h"

class MainWindow : public QObject {
    Q_OBJECT
public:
    explicit MainWindow() {
        engine_.rootContext()->setContextProperty("myModel", &model_);
        engine_.load(QUrl(QStringLiteral("qrc:/main.qml")));
    }
private:
    TableModel model_;
    QQmlApplicationEngine engine_;
};

main.qml

import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

import Qt.labs.settings 1.0
import Qt.labs.platform 1.0 as Platform

import QtQuick.Controls.Material 2.12

ApplicationWindow {
    id: window
    visible: true
    width: 1040
    height: 480
    ColumnLayout{
        spacing: 2
        anchors.fill: parent
        Button {
            text: qsTr("Update List Model")
            onClicked: myModel.addPerson()
        }
        TableView {
            width: 400
            height: 200
            columnSpacing: 1
            rowSpacing: 1
            clip: true
            ScrollIndicator.horizontal: ScrollIndicator { }
            ScrollIndicator.vertical: ScrollIndicator { }
            model: myModel
            delegate: Rectangle {
                implicitWidth: 100
                implicitHeight: 20
                border.color: "black"
                border.width: 2
                color: heading ? 'teal':"green"
                TableView.onPooled: console.log(tabledata + " pooled")
                TableView.onReused: console.log(tabledata + " resused")

                Text {
                    text: tabledata
                    font.pointSize: 10
                    anchors.centerIn: parent
                }
            }
        }
    }
}

完整的解决方案可以在这里找到

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100006649

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档