QListView更新 - 不会触发更新

时间:2015-05-23 20:43:00

标签: c++ qt paintevent

我有以下 问题:

当我在update()上致电QListView时,其paintEvent() 已触发,除非小部件上发生其他事件(鼠标移动,获得焦点。 ..)

我正在使用 Qt 4.8.3 ,除非这绝对是版本中的错误,否则我宁愿不升级(因为从我的经验升级中承担的麻烦比好处)。

问题: 如何让QListView(和Q...View)在下次主循环获得控制时更新?

某些背景 正如我所解决的那样:如果有帮助的话:

作为单线程应用程序。

底部是一些独立(无Qt)模型,它是分层的,消费者请求子项。可以修改层次结构底部的项目。

在修改时,消费者请求 W(可归属)项目。此时,受变更报告影响的模型部分"已修改"通过观察者方法。因此,观察者会在更改开始时通知(模型返回可写对象,在更改结束时无法控制或想法)。

预期消费者在从开始修改的函数/方法返回之前完成修改。

预计修改方法/函数将从主线程调用,因此下次主线程修改器与GUI,模型处于一致状态,消费者可以刷新。

QModel用于以Qt无障碍格式提供以下模型的数据。

接下来是QWidget s(列表/文本框/标签),向用户显示数据, 修改它们以支持Desync()方法,该方法将可视化数据标记为不同步,并覆盖paintEvent,以检查inSync状态。对于简单的QWidget标签,在同步时,会调用回调,它只会填充数据。对于Q...View,我假设强制模型发出modelReset,因此列表会重新加载行数和可见行的内容。

在顶部是类,在其区域下收集所有内容,这些区域与观察者相关联,以及报告的更改Desync相关小部件。

所有更改任何内容的方法都通过信号/插槽Qt thingie连接到按钮/组合框/其他GUI元素,因此我假设它全部在主线程下运行。

变革理念:

  • GUI引发事件,主线程开始处理消费者的更改方法
  • 使用者获取必要的更改项目
  • 使用者获取可写项目
  • 真实模型报告已修改为观察员
  • 观察员标记(Desync)相关QWidget s不同步
  • QWidget被标记为不同步,并计划更新,但不会尝试访问任何内容,因为我们在主线程下运行
  • 使用者执行更改,在此期间实际模型可能会不一致
  • 使用者将控件返回到任何名为
  • 的控件
  • 主循环执行更新,这些更新被覆盖以同步小部件

*我观察到的内容:*

    对于大多数没有模型的小工具,
  • update()会产生paintEvent(标签/文本框...)
  • update()不会导致paintEvent
  • QListView
  • repaint()没有帮助(只是疯狂的尝试)
  • 将鼠标移到窗口小部件上会产生paintEventQWidget同步
  • 立即尝试重新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(或者甚至以后几个循环)。

1 个答案:

答案 0 :(得分:2)

你做错了。 请勿触摸您不必的QListView。只需修复数据模型(Qt),其余部分即可开箱即用。

您的模型myModel应该只在数据发生变化时调用正确的方法。该模型应该观察真实数据的来源。 当数据发生变化时:

如果你这样做,没有别的东西需要。