使用QTableView

2100阅读 0评论2015-09-21 lzj123
分类:C/C++

在本例子中,从文本文件中读取行列的内容并利用QTableView表示在画面上。

文件结构同csv文件相似,第一行为标题,各个列之间有逗号(,)分割。
下面这个类实现读取文件并为模型类提供必要的接口。

点击(此处)折叠或打开

  1. class QMemberFile : public QFile
  2. {
  3. public:
  4.     QMemberFile(const QString& fileName) : QFile(fileName) { m_bOpened = false; }
  5.     ~QMemberFile() { if (m_bOpened) close(); }
  6.     bool readFile();

  7.     int rowCount() { return m_nRowCount - 1; }
  8.     int colCount() { return m_nColCount; }
  9.     QString content(int row, int col) { return m_Contents[row].at(col); }

  10. private:
  11.     bool m_bOpened;
  12.     int m_nRowCount;
  13.     int m_nColCount;
  14.     QVector<QStringList> m_Contents;
  15. };

  16. bool QMemberFile::readFile()
  17. {
  18.     m_nRowCount = 0;
  19.     m_nColCount = 0;

  20.     if (!this->open(QIODevice::ReadOnly | QIODevice::Text))
  21.     {
  22.          m_bOpened = false;
  23.          return false;
  24.     }
  25.     m_bOpened = true;

  26.     while (!this->atEnd())
  27.     {
  28.         QByteArray line = this->readLine();
  29.         QString sLine = line;
  30.         sLine = sLine.trimmed();
  31.         if (sLine.size() == 0)
  32.         {
  33.             continue;
  34.         }
  35.         m_Contents.push_back(sLine.split(","));
  36.         m_nRowCount++;
  37.     }
  38.     if (m_nRowCount > 0)
  39.     {
  40.         m_nColCount = m_Contents[0].count();
  41.     }

  42.     return true;
  43. }

实现一个模型类,这个类需要继承QAbstractTableModel, 需要实现下面几个函数。

int rowCount(const QModelIndex& parent) const;
int columnCount(const QModelIndex& parent) const;
QVariant data(const QModelIndex& index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;

如果要实现一个可编辑的视图,还需要实现下面的两个函数。

bool setData(const QModelIndex& index, const QVariant& value, int role);
Qt::ItemFlags flags(const QModelIndex& index);

本例子中我们实现一个只读的视图。下面是模型类的声明和实现

点击(此处)折叠或打开

  1. class CMemberTableModel : public QAbstractTableModel
  2. {
  3. public:
  4.     CMemberTableModel(QObject* parent = 0) : QAbstractTableModel(parent) { m_pMemFile = NULL; }

  5.     void setFileName(const QString& sFileName);
  6.     int rowCount(const QModelIndex& parent) const;
  7.     int columnCount(const QModelIndex& parent) const;
  8.     QVariant data(const QModelIndex& index, int role) const;
  9.     QVariant headerData(int section, Qt::Orientation orientation, int role) const;

  10. private:
  11.     QMemberFile* m_pMemFile;
  12. };

  13. void CMemberTableModel::setFileName(const QString& sFileName)
  14. {
  15.     reset();
  16.     delete m_pMemFile;
  17.     m_pMemFile = new QMemberFile(sFileName);
  18.     m_pMemFile->readFile();
  19. }

  20. int CMemberTableModel::rowCount(const QModelIndex& parent) const
  21. {
  22.     return m_pMemFile->rowCount();
  23. }

  24. int CMemberTableModel::columnCount(const QModelIndex& parent) const
  25. {
  26.     return m_pMemFile->colCount();
  27. }

  28. QVariant CMemberTableModel::data(const QModelIndex& index, int role) const
  29. {
  30.     if (!index.isValid() || m_pMemFile == NULL)
  31.     {
  32.         return QVariant();
  33.     }

  34.     if (role == Qt::DisplayRole)
  35.     {
  36.         return m_pMemFile->content(index.row()+1, index.column());
  37.     }

  38.     return QVariant();
  39. }

  40. QVariant CMemberTableModel::headerData(int section, Qt::Orientation orientation, int role) const
  41. {
  42.     if (role != Qt::DisplayRole)
  43.     {
  44.         return QVariant();
  45.     }

  46.     if (orientation == Qt::Horizontal)
  47.     {
  48.         return m_pMemFile->content(0, section);
  49.     }
  50.     else
  51.     {
  52.         return QString::number(section+1);
  53.     }

  54.     return QVariant();
  55. }

这个程序的主画面是一个继承自QDialog的对话框,对话框里包含两个空间,上面是一个组合框(QComboBox),下面是一个表视图(QTableView).
组合框里可以选择文件名,在QTableView中表示选中文件的内容。

点击(此处)折叠或打开

  1. class table_modelview : public QDialog
  2. {
  3.     Q_OBJECT

  4. public:
  5.     table_modelview(QWidget *parent = 0, Qt::WFlags flags = 0);
  6.     ~table_modelview();

  7.     void dispFile(const QString& fileName);
  8.     void addFile(const QString& fileName);

  9. private slots:
  10.     void onFileChanged(const QString& sFileName);

  11. private:
  12.     Ui::table_modelviewClass ui;

  13.     CMemberTableModel* m_pMemModel;
  14. };

  15. table_modelview::table_modelview(QWidget *parent, Qt::WFlags flags)
  16.     : QDialog(parent, flags)
  17. {
  18.     ui.setupUi(this);

  19.     setLayout(ui.mainVLayout);
  20.     m_pMemModel = new CMemberTableModel(this);
  21. }

  22. table_modelview::~table_modelview()
  23. {
  24.     delete m_pMemModel;
  25. }

  26. void table_modelview::dispFile(const QString& fileName)
  27. {
  28.     m_pMemModel->setFileName(fileName);
  29.     //ui.tvContents->setModel(NULL);
  30.     ui.tvContents->setModel(m_pMemModel);
  31. }

  32. void table_modelview::onFileChanged(const QString& sFileName)
  33. {
  34.     dispFile(sFileName);
  35. }

  36. void table_modelview::addFile(const QString& fileName)
  37. {
  38.     ui.cbFileList->addItem(fileName);
  39. }

在main函数中初始化组合框。

点击(此处)折叠或打开

  1. int main(int argc, char *argv[])
  2. {
  3.     QApplication a(argc, argv);
  4.     table_modelview w;
  5.     w.addFile("D:/test_modelview.txt");
  6.     w.addFile("D:/test_modelview1.txt");
  7.     w.show();
  8.     return a.exec();
  9. }

需要注意的地方是函数setFileName中对reset的调用,如果没有调用reset, 切换文件时视图里的数据不会刷新,
还有一种方式是在调用setModel()设置视图的模型之前,先执行setModel(NULL)。



上一篇:一个简单的文件管理工具
下一篇:初学QT