通过c ++模型在QML中设置主窗口数据

问题描述

我想在运行时使用QAbstractListModel设置Qt Quick应用程序的主窗口的x / y位置和宽度/高度。我有一个模型,它可以与Repeaterdelegate一起使用,但是我不知道如何在委托人外部访问它。

这是我的代码
model.h:

#ifndef MODEL_H
#define MODEL_H

#include <QAbstractListModel>
#include <QVector>

class Model : public QAbstractListModel {
  Q_OBJECT

public:
  int rowCount(const QModelIndex&) const override;
  QVariant data(const QModelIndex& index,int role) const override;

public slots:
  void insert(QObject& item);
  void insert(QObject* item);
  void remove(QObject* item);
  void clear();

protected:
  QHash<int,QByteArray> roleNames() const override;

private:
  QVector<QObject*> mItems;
};

#endif // MODEL_H

rectangleclass.h:

#ifndef RECTANGLECLASS_H
#define RECTANGLECLASS_H

#include <QQuickItem>

class RectangleClass : public QObject
{
private:
    Q_OBJECT
    Q_PROPERTY(int xPos READ xPos WRITE setXPos NOTIFY xPosChanged)
    Q_PROPERTY(int yPos READ yPos WRITE setYPos NOTIFY yPosChanged)
    int m_xPos;
    int m_yPos;

public:
    RectangleClass () {}
    int xPos() const { return m_xPos; }
    int yPos() const { return m_yPos; }

public slots:
    void setXPos(int arg)
    {
        if (m_xPos == arg)
            return;

        m_xPos = arg;
        emit xPosChanged(arg);
    }

    void setYPos(int arg)
    {
        if (m_yPos == arg)
            return;

        m_yPos = arg;
        emit yPosChanged(arg);
    }

signals:
    void xPosChanged(int arg);
    void yPosChanged(int arg);
};

#endif // RECTANGLECLASS_H

main.cpp:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QTimer>
#include <iostream>
#include "model.h"
#include "rectangleclass.h"

int main(int argc,char *argv[])
{


    QGuiApplication app(argc,argv);

    Model* internalModel = nullptr;
    internalModel = new Model;

    RectangleClass* newObj = nullptr;
    newObj = new RectangleClass;

    newObj->setXPos(500);
    newObj->setYPos(500);
    std::cout << "xPos: " << newObj->xPos() << " yPos: " << newObj->yPos() << std::endl;
    internalModel->insert(newObj);


    QQmlApplicationEngine engine;

    engine.rootContext()->setContextProperty("internalModel",internalModel);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

model.cpp:

#include "model.h"

int Model::rowCount(const QModelIndex&) const {
  return mItems.size();
}

QVariant Model::data(const QModelIndex& index,int /*role*/) const {
  QObject* item = mItems.at(index.row());
  return QVariant::fromValue(item);
}

void Model::insert(QObject& item) {
  beginInsertRows(QModelIndex(),0);
  mItems.push_front(&item);
  endInsertRows();
}

void Model::insert(QObject* item) {
  beginInsertRows(QModelIndex(),0);
  mItems.push_front(item);
  endInsertRows();
}

void Model::remove(QObject* item) {
  for (int i = 0; i < mItems.size(); ++i) {
    if (mItems.at(i) == item) {
      beginRemoveRows(QModelIndex(),i,i);
      mItems.remove(i);
      endRemoveRows();
      break;
    }
  }
}

void Model::clear() {
    if (!mItems.isEmpty())
    {
        beginRemoveRows(QModelIndex(),mItems.size()-1);
        mItems.clear();
        endRemoveRows();
    }
}

QHash<int,QByteArray> Model::roleNames() const {
  QHash<int,QByteArray> roles;
  roles[Qt::UserRole + 1] = "item";
  return roles;
}

main.qml:

import QtQuick 2.9
import QtQuick.Window 2.2

Window {

    visible: true
    x: 500  //internalModel.data(0).xPos
    y: 500  //internalModel.data(0).yPos
    width: 1640
    height: 1480
    title: qsTr("Hello World")

    Rectangle {
        x: 450
        y: 450
        width: 50
        height: 50
        color:"red"
    }

    Repeater {
        model: internalModel

        delegate: Rectangle {
            x: modelData.xPos
            y: modelData.yPos
            width: 400
            height: 400
            color:"yellow"
            Text {
                anchors.centerIn: parent
                text: "X-Position: " + modelData.xPos + " Y-Position: " + modelData.yPos
            }
        }
    }
}

解决方法

我认为您需要放弃整个模型/中继器的想法。只需直接公开您的RectangleClass。

    RectangleClass* newObj = new RectangleClass;
    newObj->setXPos(500);
    newObj->setYPos(500);

    QQmlApplicationEngine engine;

    engine.rootContext()->setContextProperty("rectModel",newObj);

然后在QML中,您只需访问属性即可。

Rectangle {
    x: rectModel.xPos
    y: rectModel.yPos
    width: 400
    height: 400
    color:"yellow"
    Text {
        anchors.centerIn: parent
        text: "X-Position: " + rectModel.xPos + " Y-Position: " + rectModel.yPos
    }
}