Проблема с QTableView и QStandardItemModel - PullRequest
0 голосов
/ 21 марта 2020

Я сталкиваюсь со странной вещью, когда динамически добавляю элементы в мою QStandardItemModel и показываю их с помощью QTableView. Если время между событиями достаточно велико (например, 50 мс), то представление можно прокручивать, но в случае более быстрого события (10 мс) оно всегда прокручивается вниз и не позволяет мне что-либо делать.

Вот простой фрагмент кода:

main. cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

mainwindow.h

#include <QMainWindow>
#include <QTimer>
#include <QTableView>
#include <QStandardItemModel>


QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    QTimer dataTimer;

    QStandardItemModel *model;
    QTableView *view;

public slots:
    void insertData();
};

mainwindow. cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTime>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    view = new QTableView(this);
    this->setCentralWidget(view);

    model = new QStandardItemModel(this);
    model->setColumnCount(1);
    view->setModel(model);

    QObject::connect(&dataTimer, &QTimer::timeout, this, &MainWindow::insertData);
    dataTimer.start(10); // 50 here gives correct behaviour while 10 does not
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::insertData()
{
    QList<QStandardItem *> items;
    items.append(new QStandardItem(QTime::currentTime().toString("hh:mm:ss.zzz")));

    model->insertRow(0, items);
    if (model->rowCount() > 20){
        model->removeRow(model->rowCount()-1);
    }
}

dataTimer.start (50) работает нормально, а dataTimer.start (10) тормозит поведение. Это для моего ноутбука и, возможно, для кого-то другого числа будут другими, но я думаю, что logi c понятен.

Я думал, что это слишком быстро, и некоторые методы, такие как beginInsertRows (), не ' не работает хорошо. Но это обычно для нестандартных моделей, а здесь это просто стандарт.

Может кто-нибудь сказать мне, почему это происходит? Спасибо

Ответы [ 2 ]

1 голос
/ 22 марта 2020
Таймер

10 мс в потоке GUI, влияющий на элементы GUI, - сама по себе плохая идея. Например, в Windows 10 мс таймаут недостижим стандартными средствами. Действительно ли ваш пользователь должен видеть обновления некоторых табличных данных чаще, чем 1 раз в секунду? Что ему действительно нужно? Исходя из этого, вы должны определить метод оптимизации.

Тогда вы можете выбрать:

  1. Уменьшить время ожидания таймера и повлиять на несколько строк каждого события. Похоже, вам все равно нужно уменьшить тайм-аут таймера GUI.
  2. Зарезервируйте необходимое количество строк заранее, например, на model->setRowCount(n);
  3. Временно отключить refre таблицы sh с помощью setUpdatesEnabled () метод:

    setUpdatesEnabled (false);
    bigVisualChanges ();
    setUpdatesEnabled (true);

  4. Подкласс одного из классов модели Qt и переопределение insertRows () или что-то еще.

Чтение
Получить ещё пример .
Qt Model / View Programming .

0 голосов
/ 22 марта 2020

HelloThere. Итак, когда таймер установлен на 10 мс, он добавляет и удаляет строку с каждым экраном refre sh.

Qtimer связан с частотой обновления экрана sh. Это означает, что если таймер отключится менее чем за 16 мс, он будет go выключаться при каждом обновлении экрана sh.

Когда вы добавляете элемент в список, Qt запускает в списке дополнительные события пользовательского интерфейса для разметки и просмотра границ. Поскольку вы добавляете и удаляете при каждом обновлении экрана sh, ваш список застрял в константе l oop запуска этих событий. Не говоря уже о том, что ваш список по сути заменяется каждые 20 кадров.

Я не уверен, почему вам нужно так часто добавлять элементы в список, но, возможно, вам следует пакетно добавлять и удалять в список, а затем каждые 100 мсек вы можете выполнять массовое добавление и удаление? Это решило бы проблему.

...