0

如果我们使用以下 QT 功能从 SQL 数据库中获取数据

 QSqlQueryModel *model = new QSqlQueryModel;
 model->setQuery("SELECT name, salary FROM employee");

它在随附的材料中指出,我们可以使用以下任一命令访问单个元素

 int salary = model.record(4).value("salary").toInt();

或者

 int salary = model.data(model.index(4, 2)).toInt();

并且我们可以将这些数据插入到 QTableView 使用

 QTableView *view = new QTableView;
 view->setModel(model);

而且这些数据也可以但是,我可以在任何地方看到如何提取整列数据或列/行范围(或如在 QSqlQueryModel 索引和角色的术语中)。

最终,我想做的是将部分数据有效地提取到 QVectors 中,例如数据的第 3 列。或者可能使用某种 getDataFunc(QVector rows, QVector columns) 进入矩阵库,如犰狳或 Eigen。

我正在处理的数据可能很大,因此高效很重要,因此使用一组幼稚的 for 循环似乎是一个非常糟糕的主意。

非常感谢任何帮助。

4

1 回答 1

4

我建议看看 QAbstractProxyModel。特别是考虑到你有一个巨大的数据集,所以在不同的地方复制它们对我来说并不好。

所以在代码语言中,我想我会创建类似的东西:

class RowsInColumnProxyModel: public QAbstractProxyModel {

  ....

  void setTargetColumn( int column );
  void setRowsRange(int minRow, int maxRow);

  int rowCount(..);
  int columnCount(..);

  ... whatever else on your taste from QAbstractItemModel ... 

  virtual QModelIndex   mapFromSource(const QModelIndex & sourceIndex) const;
  virtual QModelIndex   mapToSource(const QModelIndex & proxyIndex) const;
}

您可能想查看 Qt 文档,因为有很多可用的示例。想法是,在 mapFrom 和 mapTo 函数中,您提供了一个逻辑,将列中的索引映射到完整数据集中的索引,以及 rows() 和 columns() 的正确值。休息会自动为您完成,只要 ProxyModel只是一个模型,您可以在任何 UI 控件或您喜欢的任何其他方式中使用它。我经常使用代理模型,一旦你习惯了它就会非常方便。

我将尝试举一些例子,希望它能让你清楚... Qt 中的模型(无论它具有什么类型),是一组数据。根据类型的不同,它可以是具有行和列的表(显然,具有一列的模型是列表),或者更高级的东西,例如树,您可以在其中拥有更复杂的层次结构,但我们现在暂且不谈。

因此,QSqlQueryModel 是一个包含行和列的平面表,其中行 - 是结果集中的许多记录,列是您通过查询获取的列数。

假设你有类似的东西

Col1 Col2 Col3

1 2 a 4 3 v 5 ff

从数学的角度来看,您可以将其称为矩阵。

QModelIndex - 是一个代表模型中“位置”的类。为了简单起见,您可以将其视为代表 pair { row, column }

所以你可以使用方法从模型中获取数据

 QVariant data( QModelIndex, DisplayRole)

此方法将返回位于 QModelIndex 描述的位置的单元格的内容。要转换物理行和列,您应该使用方法

QModelIndex index(int row, int column, QModelIndex & parent = QModelIndex()); 

您现在可以忽略最后一个参数(它仅用于树模型),因此要从平面表模型(QSqlRecordModel 是)中获取任何单元格,您可以使用如下代码:

 QVariant value = model.data( model.index( row, column) );
 int      intValue = value.toInt();

 .. or in case you expect a string

 QString  strValue = value.toString()

 .. etc

所以,接近主题......你的任务是提取一个向量,所以让我们说任何矩阵列的一部分......所以你定义一个类,如:

 class Vector: public QAbstractProxyModel {
     protected:

         // make them =0 in constructor

         int        m_column;
         int        m_minRow;
         int        m_maxRow;

      ...

         void  setTargetColumn( int column ) {
            // emitting signals important to let rest of the world now about changes
            emit beginResetModel();
            m_column = column;
            emit endResetModel();
         }

         void setRowsRange( int minRow, int maxRow ) {
            // emitting signals important to let rest of the world now about changes
            emit beginResetModel();
            m_minRow = minRow;
            m_maxRow = maxRow;
            emit endResetModel();             
         }

         virtual int columnCount(const QModelIndex & parent = QModelIndex()) {
            return 1;  // since it's vector
         }

         virtual int rowCount(const QModelIndex & parent = QModelIndex()) {
            return m_maxRow - m_minRow;
         }

         .. now most exciting part..

         virtual QModelIndex   mapFromSource(const QModelIndex & sourceIndex) const {
             int sourceRow = sourceIndex.row();
             int sourceColumn = sourceIndex.column();

             int targetColumn = 0; // only one in vector
             int targetRow = sourceRow - m_minRow;

             return modelIndex( targetRow, targetColumn );
         }

         virtual QModelIndex   mapToSource(const QModelIndex & proxyIndex) const {
             // same as above but a bit shorter

             return index( proxyIndex.row()+m_minRow, m_column );
         }       
 }

好的,我们有一个类让我们使用它

 QSqlRecordModel * sourceModel = ... (so, it's something)
 Vector * myVector = new Vector();
 myVector->setSourceModel( sourceModel );
 myVector->setTargetColumn(3);
 myVector->setRowsRange(5, 10);

 ...

 for (int i=0;i<myVector->rowCount();i++) {
     int vectorItem = myVector->data( myVector->index(i,0) ).toInt();
 }

希望它能解释更多,我的回答是什么意思

于 2013-08-08T16:13:19.310 回答