QML 表视图实时刷新仅每 1 秒更新一次 UI



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

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

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

主.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()
}
}

}

生命游戏模型.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]

游戏生活模型.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]

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

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);

最新更新