是否可以将一个和相同的源数据集与不同的表模型链接?

时间:2019-05-28 09:50:49

标签: c++ qt qt5 qtableview qabstracttablemodel

假设我具有类型为 QString 的源数据结构。我的目标是在不同模型( QAbstractTableModel )呈现的不同表( QTableView )中显示此数据。我想在源数据更改时看到这些表中的数据更改,但是没有为每个表模型显式调用 setData (...)。 有可能吗?

------ UPD -------为我的示例添加了代码。我不知道该如何处理。

我不知道如何对不同的表使用相同的模型。 如果您知道,请告诉我如何操作。这是我的测试示例。

#TableTest.pro

    QT += widgets
    DEFINES += QT_DEPRECATED_WARNINGS

    SOURCES += \
            main.cpp

    HEADERS += \
        main.h
    # Default rules for deployment.
    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target

// main.h
    #include <QObject>
    #include <QTimer>
    #include <QString>
    #include <QColor>
    #include <QTableView>
    #include <QHeaderView>
    #include <QStandardItemModel>
    #include <QStringList>

    #define UPDATE_INTERVAL 200
    #define MAP_WIDTH 600
    #define MAP_HEIGHT 400
    #define RAND_HALF (RAND_MAX / 2)

    #ifndef MAIN_H
    #define MAIN_H

    class CTestObject : public QObject
    {
        Q_OBJECT

    public:

        CTestObject(QString name, QString user);
        void setData(double x, double y, double speed, const QString &zone);
        void setData(double speed, double azimuth);

        QString Name;
        QString User;
        double CoordX;
        double CoordY;
        double Speed;
        double Azimuth;
        double Weight;
        QColor Color;
        QString Zone;

    signals:
        void changed(CTestObject*);
    };
    //--------------------------------------------- All Objects Table
    class CAllObjectsTable : public QStandardItemModel
    {
        Q_OBJECT

    public:
        CAllObjectsTable(QString Title, QStringList ColumnHeaders);
        void addRecord(CTestObject *object);
        void deleteRecord(CTestObject *object);

        QTableView *view;

    public slots:
        virtual void updateRecordData(CTestObject *object);

    protected:
        QVector<CTestObject*> Objects; // local array pointers to objects (each table has its own set)
    };
    //--------------------------------------------- Table Zone
    class CZoneTable : public CAllObjectsTable
    {
        Q_OBJECT

    public:
        CZoneTable(QString Title, QStringList ColumnHeaders) : CAllObjectsTable(Title, ColumnHeaders){}
        void addRecord(CTestObject *object);

    public slots:
        virtual void updateRecordData(CTestObject *object) override;
    };
    //-------------------------------------------- Users Table
    class CUsersTable : public CAllObjectsTable
    {
        Q_OBJECT

    public:
        CUsersTable(QString Title, QStringList ColumnHeaders) : CAllObjectsTable(Title, ColumnHeaders){}
        void addRecord(CTestObject *object);

    public slots:
        virtual void updateRecordData(CTestObject *object) override;
    };

    #endif // MAIN_H

// main.cpp
#include <QApplication>
#include <QtMath>
#include <QDebug>
#include "main.h"

void tmrUpdateEvent();
QVector<CTestObject*> g_Objects; // Global source objects array
CAllObjectsTable *AllObjectsTable;
CZoneTable *ZoneObjectsTable;
CUsersTable *UsersTable;
//-----------------------------------------------------------------
int main(int argc, char *argv[])
{
QApplication app(argc, argv);

    // create objects
    g_Objects.append(new CTestObject("ObjectA", "John"));
    g_Objects.append(new CTestObject("ObjectB", "Peter"));
    g_Objects.append(new CTestObject("ObjectC", "Mike"));
    g_Objects.append(new CTestObject("ObjectD", "Alice"));
    g_Objects.append(new CTestObject("ObjectE", "Megan"));

    // create tables
    AllObjectsTable = new CAllObjectsTable("All Objects", QStringList() << "Object" << "X" << "Y" << "Speed" << "Zone");

    for(int c =0; c < g_Objects.size(); c++)
        AllObjectsTable->addRecord(g_Objects[c]);

    ZoneObjectsTable = new CZoneTable("Zone B1", QStringList() << "Object" << "Weight" << "Speed" << "Azimuth" << "X" << "Y");
    UsersTable = new CUsersTable("Users", QStringList() << "User" << "Object" << "Zone" << "X" << "Y");

    tmrUpdateEvent();

return app.exec();
}
//------------------------------------------------ Table AllObjects
CAllObjectsTable::CAllObjectsTable(QString Title, QStringList ColumnHeaders)
{
    // model
    this->setHorizontalHeaderLabels(ColumnHeaders);

    // view
    view = new QTableView;
    view->setWindowTitle(Title);
    view->verticalHeader()->hide();
    view->setModel(this);
    view->show();
}

void CAllObjectsTable::addRecord(CTestObject *object)
{
    if(!object)
        return;

    this->Objects.append(object);
    this->insertRow(this->Objects.size() - 1);
    this->setData(index((Objects.size() - 1), 0), object->Name, Qt::DisplayRole);

    connect(object, SIGNAL(changed(CTestObject*)), this, SLOT(updateRecordData(CTestObject*)));
}

void CAllObjectsTable::deleteRecord(CTestObject *object)
{
    for(int c =0; c < this->Objects.size(); c++)
        if(this->Objects[c] == object)
        {
            this->Objects.remove(c);
            this->removeRow(c);
        }
}

void CAllObjectsTable::updateRecordData(CTestObject *object)
{
    for(int c =0; c < this->Objects.size(); c++)
        if(this->Objects[c] == object)
        {
            this->setData(index(c, 1), object->CoordX, Qt::DisplayRole);
            this->setData(index(c, 2), object->CoordY, Qt::DisplayRole);
            this->setData(index(c, 3), object->Speed, Qt::DisplayRole);
            this->setData(index(c, 4), object->Zone, Qt::DisplayRole);
        }
}
//------------------------------------------------------- Table Zone
void CZoneTable::addRecord(CTestObject *object)
{
    if(!object)
        return;

    this->Objects.append(object);
    this->insertRow(Objects.size() - 1);
    this->setData(index((this->Objects.size() - 1), 0), object->Name, Qt::DisplayRole); // Name
    this->setData(index((Objects.size() - 1), 1), object->Weight, Qt::DisplayRole); // Weight

    connect(object, SIGNAL(changed(CTestObject*)), this, SLOT(updateRecordData(CTestObject*)));
}

void CZoneTable::updateRecordData(CTestObject *object)
{
    for(int c =0; c < this->Objects.size(); c++)
        if(this->Objects[c] == object)
        {

            this->setData(index(c, 2), object->Speed, Qt::DisplayRole); // Speed
            this->setData(index(c, 3), object->Azimuth, Qt::DisplayRole); // Azimuth
            this->setData(index(c, 4), object->CoordX, Qt::DisplayRole); // X
            this->setData(index(c, 5), object->CoordY, Qt::DisplayRole); // Y
        }
}
//------------------------------------------------------- Table Users
void CUsersTable::addRecord(CTestObject *object)
{
    if(!object)
        return;

    this->Objects.append(object);
    this->insertRow(Objects.size() - 1);
    this->setData(index((this->Objects.size() - 1), 0), object->User, Qt::DisplayRole); // User
    this->setData(index((Objects.size() - 1), 1), object->Name, Qt::DisplayRole); // Name
    this->setData(index((Objects.size() - 1), 0), object->Color, Qt::ForegroundRole);

    connect(object, SIGNAL(changed(CTestObject*)), this, SLOT(updateRecordData(CTestObject*)));
}

void CUsersTable::updateRecordData(CTestObject *object)
{
    for(int c =0; c < this->Objects.size(); c++)
        if(this->Objects[c] == object)
        {
            this->setData(index(c, 2), object->Zone, Qt::DisplayRole); // Zone
            this->setData(index(c, 3), object->CoordX, Qt::DisplayRole); // X
            this->setData(index(c, 4), object->CoordY, Qt::DisplayRole); // Y
        }
}
//------------------------------------------------------- Object
CTestObject::CTestObject(QString name, QString user) : Name(name), User(user)
{
    Weight =(std::rand() % 20000);
    Color =(std::rand() << 15 | std::rand());
    setData((std::rand() % MAP_WIDTH), (std::rand() % MAP_HEIGHT), 0, "");
    setData(std::rand(), ((double)(std::rand() - RAND_HALF) / RAND_MAX));
}

void CTestObject::setData(double x, double y, double speed, const QString &zone)
{
    this->CoordX =x;
    this->CoordY =y;
    this->Speed =speed;
    this->Zone =zone;

    emit changed(this);
}

void CTestObject::setData(double speed, double azimuth)
{
    this->Speed =std::fmod(speed, 1000);
    this->Azimuth =azimuth;

    emit changed(this);
}
//----------------------------------------------------------
QString GetZoneXY(double x, double y)
{
double ZoneWidth =(MAP_WIDTH / 3), ZoneHeight =(MAP_HEIGHT / 3);
QString Zone ="";

    if(x < ZoneWidth)
        Zone +="A";
    else
    if(x < (ZoneWidth * 2))
        Zone +="B";
    else
        Zone +="C";

    if(y < ZoneHeight)
        Zone +="0";
    else
    if(y < (ZoneHeight * 2))
        Zone +="1";
    else
        Zone +="2";

return(Zone);
}
//============================================== Update =================================
void tmrUpdateEvent()
{
    for(int c =0; c < g_Objects.size(); c++)
    {
    double s;

        s =(g_Objects[c]->Speed - (0.001 * g_Objects[c]->Weight));

        if(s > 10) // if Object moving - update Coords & Speed
        {
        double x =g_Objects[c]->CoordX, y =g_Objects[c]->CoordY, a =g_Objects[c]->Azimuth;
        QString z;

            x =std::fmod(x + (std::sin(a) * s * 0.01), MAP_WIDTH);
            y =std::fmod(y + (std::cos(a) * s * 0.01), MAP_HEIGHT);

            while(x < 0)
                x +=MAP_WIDTH;

            while(y < 0)
                y +=MAP_HEIGHT;

            z =GetZoneXY(x, y); // current zone

            // check objects for Zone table
            if(g_Objects[c]->Zone == "B1" && z != "B1")
                ZoneObjectsTable->deleteRecord(g_Objects[c]);
            else
            if(z == "B1" && g_Objects[c]->Zone != "B1")
                ZoneObjectsTable->addRecord(g_Objects[c]);

            // check objects for Users table
            if(z != "B1" && g_Objects[c]->Zone == "B1")
                UsersTable->addRecord(g_Objects[c]);
            else
            if(z == "B1" && g_Objects[c]->Zone != "B1")
                UsersTable->deleteRecord(g_Objects[c]);

            g_Objects[c]->setData(x, y, s, z);
        }
        else // new Speed & Direction
            g_Objects[c]->setData(std::rand(), ((double)(std::rand() - RAND_HALF) / RAND_MAX));
    }

    QTimer::singleShot(UPDATE_INTERVAL, [=](){tmrUpdateEvent();});
}

1 个答案:

答案 0 :(得分:0)

谢谢大家。我找到了问题的答案-不,这是不可能的。 问题是setData(...)通过复制为模型设置数据。而且我想插入到它们的链接,而不是稍后再捕获有关数据更改的信号。像这样的东西。