Обновление QListView — не вызывает обновление

У меня есть следующие проблема:

когда я звоню update() на QListView, его paintEvent() является не срабатывает, если над виджетом не происходит какое-либо другое событие (перемещение мыши, получение фокуса ….)

я использую Qt 4.8.3, и если это точно не ошибка в версии, я бы предпочел не обновляется (как показывает мой опыт, обновления приносят больше хлопот, чем пользы).

Вопрос:
Как сделать QListView (а также Q...View) обновить в следующий раз, когда основной цикл получит контроль?

Некоторый фон как то, что я решаю, если это поможет:

Имеется в виду однопоточное приложение.

Внизу есть некоторые независимый (нет Qt) модель, который является иерархическим, и потребители запрашивают подпункты. Элементы в нижней части иерархии могут быть изменены.

На модификации, запросы потребителей W (ritable) Пункт. В этот момент на детали модели влияют отчеты об изменениях. «модифицированный» через подход наблюдателя. Таким образом, наблюдатели уведомлены в начало изменений (модель возвращает доступный для записи объект, не имеет никакого контроля или идеи, когда изменение заканчивается).

Ожидается, что потребитель завершит модификацию, прежде чем вернуться из функции / метода, который начал модификацию.

Ожидается, что модифицирующие методы / функции будут вызываться из основного потока, поэтому в следующий раз, когда основной поток будет работать с графическим интерфейсом, модель будет в согласованном состоянии, и потребители смогут обновить ее.

QModelЭто делается для предоставления данных из модели ниже в доступном формате Qt.

Далее идут QWidgets (списки / текстовые поля / метки) визуализация данных для пользователя,
они модифицированы для поддержки Desync() метод, который помечает визуализированные данные как не синхронизированные и переопределяемые paintEvent, который проверяет inSync государство. Для простого QWidgetПодобно меткам, при синхронизации вызывается обратный вызов, который просто заполняет данные. За Q...ViewЯ предполагал заставить модели излучать modelReset, поэтому список перезагружает количество строк и содержимое видимых.

На вершине класс собирает все это вместе в своем регионе, который подключен к наблюдателям, и о зарегистрированных изменениях Desync соответствующие виджеты.

Все методы, изменяющие что-либо, подключаются через Qt Thieie сигнал / слот к кнопкам / комбинированным спискам / другим элементам графического интерфейса, так что я предполагаю, что все это работает под основным потоком.

Идея перемен:

  • Событие, вызванное GUI, основной поток начинает обработку потребительизменить метод
  • потребитель получает необходимые предметы для изменения
  • потребитель получает записываемые предметы
  • реальная модель отчеты изменены наблюдателей
  • наблюдателей отметка (Desync) Соответствующий QWidgetкак не синхронизировано
  • QWidgets помечены как несинхронизированные и запланированные для обновления, но не пытаются получить доступ к чему-либо, так как мы работаем в основном потоке
  • потребитель выполняет изменение, во время которого реальная модель может быть даже противоречивой
  • потребитель возвращает контроль к тому, что называется
  • основной цикл выполняет обновления, которые переопределяются для синхронизации виджетов

* Что я заметил: *

  • update() результаты в paintEvent для большинства виджетов, у которых вообще нет модели (метка / текстовое поле …)
  • update() не приводит к paintEvent за QListView
  • repaint () не помогает (была просто дикая попытка)
  • перемещение мыши над виджетом приводит к paintEvent, а также QWidget синхронизирует
  • пытаясь visible(false); update(); visible(true); перекрашивает сразу
    • это неправильно, так как QWidget синхронизируется до того, как потребитель выполнит изменение
  • переключение окон (то есть визуальная студия) или обратно приводит к paintEvent будучи призванным

Упрощенные источники, где взять поведение:

myList.h

  #ifndef __myList_h__
#define __myList_h__

#include <qlistview.h>

class myList : public QListView
{
bool inSync;
void sync();

protected:
virtual void paintEvent(QPaintEvent * event) override;

public:
myList(QWidget * parent);
void Desync();
virtual ~myList();
};

#endif

myList.cpp

  #include "myList.h"#include "myModel.h"
void myList::sync()
{
if (inSync)
return;

inSync = true; //< set early, to prevent loops
((myModel*)model())->ResetModel();
}

void myList::paintEvent(QPaintEvent * event)
{
sync();
QListView::paintEvent(event);
}

myList::myList(QWidget * parent) : QListView(parent), inSync(false)
{}

void myList::Desync()
{
inSync = false;
update();
}

myList::~myList()
{}

myModel.h

  #ifndef __myModel_h__
#define __myModel_h__

#include <QAbstractListModel>

class myModel : public QAbstractListModel
{
Q_OBJECT;

int & externalComplexData;

public:
myModel(int & externalComplexData);

virtual int rowCount(QModelIndex const & parent = QModelIndex()) const override;
virtual QVariant data(QModelIndex const & index, int role) const override;

void ResetModel();

virtual ~myModel();

};

#endif

myModel.cpp

  #include "myModel.h"
myModel::myModel(int & externalComplexData) : externalComplexData(externalComplexData)
{}

int myModel::rowCount(QModelIndex const & parent) const
{
return 1;
}

QVariant myModel::data(QModelIndex const & index, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();

return QString::number(externalComplexData);
}

void myModel::ResetModel()
{
reset();
}

myModel::~myModel()
{}

tmp.h

  #ifndef __Tmp_H__
#define __Tmp_H__

#include <QtGui/QMainWindow>
#include "ui_tmp.h"
class tmp : public QMainWindow
{
Q_OBJECT

public:
tmp(QWidget *parent = 0, Qt::WFlags flags = 0);
~tmp();

private:
Ui::tmpClass ui;

private slots:
void clicked();
};

#endif

tmp.cpp

  #include "tmp.h"#include "myModel.h"
int localComplexData = 0;

tmp::tmp(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);

ui.lst->setModel(new myModel(localComplexData));
connect(ui.btn, SIGNAL(clicked()), this, SLOT(clicked()));
}

void tmp::clicked()
{
ui.lst->Desync();
++localComplexData;
}

tmp::~tmp()
{}

Поведение:
Нажатие кнопки обновляет внешнюю модель, но список не синхронизируется.

При наведении мыши на список, он синхронизируется.

Ожидаемое поведение:
Регистрация желания программиста update()и привести к paintEvent в следующий раз основной цикл получает управление (или даже несколько циклов позже).

0

Решение

Вы сделали это неправильно.
Не трогай QListView тебе не нужно Просто исправьте модель данных (Qt), а остальные будут работать из коробки.

Ваша модель myModel следует просто вызывать надлежащие методы при изменении данных. Эта модель должна соблюдать источник реальных данных.
Когда что-то случится с данными:

  • данные изменены — испустить сигнал dataChanged
  • данные добавлены или удалены вызов beginInsertRows а также endInsertRows или другие соответствующие версии

Если вы делаете это правильно, больше ничего не нужно.

2

Другие решения


По вопросам рекламы [email protected]