QT表/模型不调用data()

时间:2014-04-16 11:39:00

标签: qt tableview qtableview

我正在尝试创建表示表格的小部件并更新一些数据。 为了做到这一点,我遵循Qt Model/View tutorial

我已经创建了课程(你可以在帖子的末尾找到)

  • 继承自QAbstractTableModel
  • 的EmittersTableModel
  • 继承自QTableView的EmittersTableWidget

我将EmittersTableModel对象作为EmittersTableWidget的私有成员。在它的构造函数中,我实例化了模型并使用了setModel()方法。

然后,当我尝试更新数据时,我调用了EmittersTableWidget :: setRadioData()方法,然后发出datachanged()信号。

我已通过调试器验证:

  • emit dataChanged(topLeft, bottomRight)被称为
  • EmittersTableModel::rowCount()被称为
  • EmittersTableModel::columnCount()被称为
  • EmittersTableModel::flags()永远不会被称为
  • EmittersTableModel::data()永远不会被召唤。

对我而言,我正在做所有教程所说的(使用setModel(),实现所需的虚函数,发出信号)。

我失踪了什么?

EmittersTableModel.h

#include <QAbstractTableModel>
#include <QVector>
#include "Radio.h"

typedef QMultiMap<QString, MapScenario::Core::RadioPtr> PlayerRadioMap;

class EmittersTableModel : public QAbstractTableModel
{
  Q_OBJECT
public:

  EmittersTableModel(QObject *parent);
  virtual int rowCount(const QModelIndex &parent = QModelIndex()) const ;
  virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
  virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
  virtual Qt::ItemFlags flags ( const QModelIndex & index ) const;
  QVariant headerData(int section, Qt::Orientation orientation, int role) const;
  void setRadioData(const PlayerRadioMap &xRadioMap);

private:

  typedef struct
  {
    QString xName;
    MapScenario::Core::RadioPtr pxRadio;
  } TableRowData;

  PlayerRadioMap m_xRadioMap;
  QVector<TableRowData> m_xDataVector;
};

EmittersTableModel.cpp

#include "EmittersTableModel.h"

EmittersTableModel::EmittersTableModel(QObject *parent)
:QAbstractTableModel(parent)
{
}

int EmittersTableModel::rowCount(const QModelIndex & /*parent*/) const
{
  return m_xDataVector.size() - 1;
}

int EmittersTableModel::columnCount(const QModelIndex & /*parent*/) const
{
  return 8;
}

QVariant EmittersTableModel::data(const QModelIndex &index, int role) const
{
  if (role == Qt::DisplayRole)
  {
    switch (index.column())
    {
      case 0 :
      {
        return m_xDataVector.at(index.row()).xName;
      } break;
      case 1 :
      {
        return m_xDataVector.at(index.row()).pxRadio->getName();
      } break;      
    }
    return QString("Row%1, Column%2")
      .arg(index.row() + 1)
      .arg(index.column() +1);
  }
  return QVariant();
}

Qt::ItemFlags EmittersTableModel::flags(const QModelIndex &index) const
{
  return Qt::ItemIsEnabled | Qt::ItemIsEditable;
}

QVariant EmittersTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
  if (role == Qt::DisplayRole)
  {
    if (orientation == Qt::Horizontal) {
      switch (section)
      {
      case 0:
        return QString("Player");
      case 1:
        return QString("Emitter");
      case 2:
        return QString("Freq.");
      case 3:
        return QString("Power");
      case 4:
        return QString("Modulation");
      case 5:
        return QString("Freq. Hopp.");
      case 6:
        return QString("Silent");  
      case 7:
        return QString("Rec. Power");
      }
    }
  }
  return QVariant();
}

void EmittersTableModel::setRadioData(const PlayerRadioMap &xRadioMap)
{
  m_xDataVector.clear();
  PlayerRadioMap::const_iterator xIt;
  for (xIt = xRadioMap.begin(); xIt != xRadioMap.end(); ++xIt)
  {
    TableRowData xData;
    xData.xName = xIt.key();
    xData.pxRadio = xIt.value();
    m_xDataVector.append(xData);
  }

  if (false == m_xDataVector.empty())
  {
    QModelIndex topLeft = createIndex(0, 0);
    QModelIndex bottomRight = createIndex(m_xDataVector.size() - 1, 7);
    emit dataChanged(topLeft, bottomRight);
  }
}

EmittersTableWidget.h

#include <QTableView>
#include <QHeaderView>
#include <QMultiMap>
#include <boost/smart_ptr.hpp>
#include "EmittersTableModel.h"
#include "Scenario.h"
#include "Radio.h"

namespace MapScenario
{
  namespace Core
  {
    class Player;
  }
}


/** Class for the player properties table model window */
class EmittersTableWidget : public QTableView
{
    Q_OBJECT
public:

  EmittersTableWidget(QWidget *xParent = 0);
  ~EmittersTableWidget();

public slots:

  void refreshScenarioDataSlot(const MapScenario::Core::ScenarioPtr pxScenario);

private:

  EmittersTableModel *m_pxModel;

  void getTransmitterMap(const MapScenario::Core::ScenarioPtr pxScenario, PlayerRadioMap *pxRadioMap) const;
  void sendDataToTableModel(const PlayerRadioMap &xRadioMap); 
};

EmittersTableWidget.cpp

#include "EmittersTableWidget.h"
#include "Player.h"
#include "CoreException.h"

using MapScenario::Core::ScenarioPtr;
using MapScenario::Core::Radio;
using MapScenario::Core::PlayerPtr;

///////////////////////////////////////////////////////////////////////////////
// PUBLIC SECTION                                                            //
///////////////////////////////////////////////////////////////////////////////

EmittersTableWidget::EmittersTableWidget(QWidget *xParent)
 : QTableView(xParent)
{
  m_pxModel = new EmittersTableModel(0);
  setModel(m_pxModel);
  horizontalHeader()->setVisible(true);
  verticalHeader()->setVisible(false);
  setShowGrid(true);
  setGridStyle(Qt::NoPen);
  setCornerButtonEnabled(false);
  setWordWrap(true);
  setAlternatingRowColors(true);
  setSelectionMode(QAbstractItemView::SingleSelection);
  setSelectionBehavior(QAbstractItemView::SelectRows);
  setSortingEnabled(true);
}

EmittersTableWidget::~EmittersTableWidget()
{
  delete m_pxModel;
}

///////////////////////////////////////////////////////////////////////////////
// PUBLIC SLOTS SECTION                                                      //
///////////////////////////////////////////////////////////////////////////////


void EmittersTableWidget::refreshScenarioDataSlot(const ScenarioPtr pxScenario)
{
  PlayerRadioMap xRadioMap;
  getTransmitterMap(pxScenario, &xRadioMap);
  sendDataToTableModel(xRadioMap);
}

void EmittersTableWidget::getTransmitterMap(const ScenarioPtr pxScenario, PlayerRadioMap *pxRadioMap) const
{
  QVector<QString> xNameList;
  QVector<QString>::const_iterator xNameIt;
  QStringList::const_iterator xRadioIt;

  pxScenario->getPlayersNameList(xNameList);
  for (xNameIt = xNameList.begin(); xNameIt != xNameList.end(); ++xNameIt)
  {
    QStringList xRadioList;
    PlayerPtr pxPlayer = pxScenario->getPlayer(*xNameIt);
    pxPlayer->getRadioNameList(xRadioList);
    for (xRadioIt = xRadioList.begin(); xRadioIt != xRadioList.end(); ++xRadioIt)
    {
      pxRadioMap->insert(pxPlayer->getName(), pxPlayer->getRadio(*xRadioIt));
    }
  }
}

void EmittersTableWidget::sendDataToTableModel(const PlayerRadioMap &xRadioMap)
{
  m_pxModel->setRadioData(xRadioMap);
}

1 个答案:

答案 0 :(得分:0)

我发现了我的问题。

在我看过的教程中,假设行号和列号始终是常量。相反,我从零行开始,然后在需要时添加或删除它们。为此,我需要重新实现以下方法:

  • virtual bool insertRows(int row, int count, const QModelIndex &parent)
  • virtual bool insertColumns(int column, int count, const QModelIndex &parent)
  • virtual bool removeRows(int row, int count, const QModelIndex &parent)
  • virtual bool removeColumns(int column, int count, const QModelIndex &parent)

如子类化部分QAbstractItemModel page中所述。现在我在需要时插入和删除行并正确更新表。