我的任务是每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]
答案 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);