QTableView具有1000个可见单元的慢性能

时间:2013-10-30 19:00:14

标签: c++ qt

我在Qt 4.8.4中使用QTableView来显示大量数据(大量/多种蛋白质氨基酸序列),我希望能够使细胞尽可能小,这样我可以包装尽可能多的数据可能进入给定的窗口。我遇到的问题是,当同时显示许多单元格时,所有内容(例如滚动,调整大小和一般重新绘制)都会减慢到爬行速度。这是一些示例代码(改编自examples / tutorials / 1_readonly教程):

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

int MyModel::rowCount(const QModelIndex & /*parent*/) const {
   return 200;
}
int MyModel::columnCount(const QModelIndex & /*parent*/) const {
    return 60;
}
QVariant MyModel::data(const QModelIndex &index, int role) const {
    if (role == Qt::DisplayRole){
       return QString("%1").arg(index.row()%10);
    }
    return QVariant();
}

这是运行表视图的代码:

int main(int argc, char *argv[]){
   QApplication a(argc, argv);
   QTableView tableView;    
   tableView.horizontalHeader()->setDefaultSectionSize(15);
   tableView.verticalHeader()->setDefaultSectionSize(15);
   tableView.setFont(QFont("Courier",12));
   MyModel myModel(0);
   tableView.setModel( &myModel );
   tableView.setGeometry(0,0,1000,1000);
   tableView.show();
   return a.exec();
}

当我在OSX上使用Instruments上下滚动时,它会花费大量时间在QWidgetPrivate::drawWidget和堆栈中,QWidgetPrivate::paintSiblingsRecursive ...即,它花了很多时间重新绘制我的表

我是Qt的新手,所以我不确定如何解决这个问题。我应该:

  • 覆盖paint方法?也许我可以将整个表格保存为图像,当滚动发生时,只需重新绘制图像直到移动停止(然后返回直接绘制表格)?
  • 根本不使用Qt中的表格?也许我可以使用Text字段来实现我的目的?例如对于文本中的每个字母,我想要hovertext,选择,着色字母的背景等。

这两个选项似乎都是通过切换QTableView来弥补地面损失的大量工作。还有其他建议吗?

3 个答案:

答案 0 :(得分:5)

尝试使用QTreeView,但将uniformRowHeights设置为true。上次我检查过数百万件物品。

编辑:QTreeView支持表格等等!

答案 1 :(得分:4)

众所周知,QTableView在处理大型数据集时会很慢。我建议你切换到Qt Graphics View Framework。它效率更高,并且足够灵活,可以显示表格。

QGraphicsScene scene;
QFont font("Courier",12);
QFontMetrics font_metrics(font);
int padding = 2;
int column_width = font_metrics.width("X") + padding * 2;
int row_height = font_metrics.height() + padding * 2;
int rows = 200, columns = 60;
for(int x = 0; x < columns; x++) {
  for(int y = 0; y < rows; y++) {
    QGraphicsSimpleTextItem* item = scene.addSimpleText(QString().setNum(y % 10), font);
    item->setPos(x * column_width + padding, y * row_height + padding);
  }
}
for(int x = 0; x < columns + 1; x++) {
  int line_x = x * column_width;
  scene.addLine(line_x, 0, line_x, rows * row_height)->setPen(QPen(Qt::gray));
}
for(int y = 0; y < rows + 1; y++) {
  int line_y = y * row_height;
  scene.addLine(0, line_y, columns * column_width, line_y)->setPen(QPen(Qt::gray));
}
QGraphicsView view(&scene);
view.resize(700, 700);
view.show();

答案 2 :(得分:0)

我正在使用1e8行表,不得不切换到QTreeView setUniformRowHeights(true);