QML TableView实时刷新仅每1秒更新一次UI

时间:2019-07-19 09:23:43

标签: qt qml qtquick2

我的任务是每10到100毫秒(最佳到最差值)通过UI更新实时(尽可能接近)实时显示大量数据,我设法创建了一个生成随机数的测试模型,使用计时器用新的随机值集填充表格视图。我尝试在1到100毫秒之间设置不同的时间间隔,并且可以看到计时器触发并创建了新的数据集,但是无论计时器间隔值如何,UI每次都严格在1秒内更新。 您能否指导我如何在不到1秒的时间内处理UI更新。

我尝试了从50x1000的表到50x50的不同数量的数据。每次我获得1秒的UI更新速率。

它基于Qt的“生命游戏”示例,因此某些元素只是未使用且已过时,但是一旦“禁用”,我认为它们不会对其余元素产生任何影响代码和问题本身。 您可以看到,在nextStep()方法中,我将时间戳记日志记录到控制台,并且在输出中可以看到该方法是根据计时器调用的,但是UI仅每秒可视地更新一次。

main.qml

ApplicationWindow {
id: root
visible: true
width: 760
height: 810
minimumWidth: 475
minimumHeight: 300

color: "#09102B"
title: qsTr("Conway’s Game of Life")

//! [tableview]
TableView {
    id: tableView
    anchors.fill: parent

    rowSpacing: 1
    columnSpacing: 1

    ScrollBar.horizontal: ScrollBar {}
    ScrollBar.vertical: ScrollBar {}

    delegate: Rectangle {
        id: cell
        implicitWidth: 45
        implicitHeight: 15

        color: model.value > 100 ? "#f3f3f4" : "#b5b7bf"
        Label {
            width: parent.width
            height: parent.height
            text: model.value
        }
    }
    //! [tableview]

    //! [model]
    model: GameOfLifeModel {
        id: gameOfLifeModel
    }
    //! [model]

    //! [scroll]
    contentX: 0;
    contentY: 0;
    //! [scroll]
}

footer: Rectangle {
    signal nextStep

    id: footer
    height: 50
    color: "#F3F3F4"

    RowLayout {
        anchors.centerIn: parent

        //! [next]
        Button {
            text: qsTr("Next")
            onClicked: gameOfLifeModel.nextStep()
        }
        //! [next]

        Item {
            width: 50
        }

        Button {
            text: timer.running ? "❙❙" : "▶️"
            onClicked: timer.running = !timer.running
        }
    }

    FpsItem {
            id: fpsItem
            anchors.left: parent
            color: "black"
    }

    Timer {
        id: timer
        interval: 10
        running: true
        repeat: true

        onTriggered: gameOfLifeModel.nextStep()
    }
}

}

gameoflifemodel.cpp

GameOfLifeModel::GameOfLifeModel(QObject *parent)
: QAbstractTableModel(parent) {}
//! [modelsize]
int GameOfLifeModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;

    return height;
}
int GameOfLifeModel::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;

    return width;
}
//! [modelsize]

//! [read]
QVariant GameOfLifeModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || role != CellRole)
        return QVariant();

    return m_state[index.column()][index.row()];
}
//! [read]

//! [write / not used]
bool GameOfLifeModel::setData(const QModelIndex &index, const QVariant &value, int role) {
    if (role != CellRole || data(index, role) == value)
        return false;

    m_state[index.column()][index.row()] = value.toBool();
    emit dataChanged(index, index, {role});

    return true;
}
//! [write]

Qt::ItemFlags GameOfLifeModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return Qt::NoItemFlags;

    return Qt::ItemIsEditable;
}

//! [update]
void GameOfLifeModel::nextStep()
{
    srand(time(NULL));

    qDebug() << QTime::currentTime().toString("yyyy/MM/dd hh:mm:ss,zzz");

    for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
            m_state[j][i] = (rand() % 1000) + 1;
        }
    }

    emit dataChanged(index(0, 0), index(height - 1, width - 1), {CellRole});
}
//! [update]

gameoflifemodel.h

//! [modelclass]
class GameOfLifeModel : public QAbstractTableModel
{
    Q_OBJECT

    Q_ENUMS(Roles)
public:
    enum Roles {
        CellRole
    };

    QHash<int, QByteArray> roleNames() const override {
        return {
            { CellRole, "value" }
        };
    }

    explicit GameOfLifeModel(QObject *parent = nullptr);

    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    bool setData(const QModelIndex &index, const QVariant &value,
             int role = Qt::EditRole) override;

    Qt::ItemFlags flags(const QModelIndex &index) const override;

    Q_INVOKABLE void nextStep();

private:
    static constexpr int width = 50;
    static constexpr int height = 50;
    static constexpr int size = width * height;

    template <class T, size_t ROW, size_t COL>
    using NativeMatrix = T[ROW][COL];
    NativeMatrix<int, height, width> m_state;
};
//! [modelclass]

1 个答案:

答案 0 :(得分:0)

好的,问题解决了。问题似乎出在随机数生成过程中,而不是在表格视图中。 在我使用的代码中

srand(time(NULL))

time(NULL)返回秒而不是毫秒,因此我得到了相同的数字,它们仅在1秒后更新,并且在视觉上类似于仅每秒更新一次UI。为了解决这个问题,我转而使用它来生成随机数,并且一切正常:

struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);

/* using nano-seconds instead of seconds */
srand((time_t)ts.tv_nsec);