4

I'm working on an app that uses Qt's QTreeView to display hierarchical data. In some cases a single leaf in the hierarchy will contain 100,000's of child nodes.

I've discovered that QTreeView can't handle too many child nodes.

This is because when the user opens a parent node, Qt fetches ALL of the child nodes' ModelIndexes, not just the ones that are needed to fill the QTreeView display.

Why does it do this, and is there any workaround to make it fetch fewer ModelIndexes?

msrd0
  • 7,816
  • 9
  • 47
  • 82
Cedric
  • 41
  • 1
  • 1
    Have you set the view to use uniform row heights? – cmannett85 Oct 09 '14 at 22:39
  • What you mean by "can't handle". I'm working with treeviews with 1KK+ items and everything is OK. But we are using custom, performance optimized models :) – Dmitry Sazonov Oct 10 '14 at 09:25
  • By "can't handle," I mean that QT uses up all my memory and crashes. It tries to fetch ALL of the child nodes' ModelIndexes, not just the ones needed to fill the display – Cedric Oct 10 '14 at 21:26
  • What model do you use? If you run out of memory - then problem is in your model, not in view. – Dmitry Sazonov Oct 13 '14 at 08:30

1 Answers1

0

My previous answer was unfortunately useless due to QTreeWidget(I am using QTreeWidget to simplyfy) sliders cannot be set by user. Your goal could be achieved by using extra QScrollBar.

MainWidget.h

class MainWidget : public QWidget
{
    Q_OBJECT
public:
    MainWidget(QWidget *parent = 0);
private:
    QTreeWidget* Tree;
    QScrollBar* Bar;
private slots:
    void tree(QTreeWidgetItem*);
    void slider();
};

MainWidget.cpp

MainWidget::MainWidget(QWidget *parent): QWidget(parent) {
    Tree = new QTreeWidget();
    Tree->header()->hide();
    connect(Tree,SIGNAL(itemExpanded(QTreeWidgetItem*)),this,SLOT(tree(QTreeWidgetItem*)));
    Bar = new QScrollBar(Qt::Vertical);
    Bar->setRange(0,100000);
    connect(Bar,SIGNAL(sliderReleased()),this,SLOT(slider()));
    for(uint i=0;i<10;i++) {
        QTreeWidgetItem* Item=new QTreeWidgetItem(QStringList()<<QString::number(i)); //Add 10 topLevelItems
        Tree->addTopLevelItem(Item);
        for(uint j=0;j<30;j++) {
            Item->addChild(new QTreeWidgetItem(QStringList()<<QString::number(j))); //Add first 30 items
        }
    }
    QHBoxLayout* Lay = new QHBoxLayout();
    Lay->addWidget(Tree);
    Lay->addWidget(Bar);
    setLayout(Lay);
}
void MainWidget::tree(QTreeWidgetItem* I) { //SLOT Only one item expanded
    Tree->blockSignals(true); //Block SIGNAL(itemExpanded())
    Tree->collapseAll();
    Tree->expandItem(I);
    Tree->blockSignals(false);//Allow SIGNAL(itemExpanded())
}
void MainWidget::slider() { //SLOT manage tree
    for (int i=0;i<Tree->topLevelItemCount();i++) {
        if (Tree->topLevelItem(i)->isExpanded()) {
            for(uint j=Tree->topLevelItem(i)->childCount(); j>0;j--) { //Clear children
                delete Tree->topLevelItem(i)->child(j-1);
            }
            uint Value = Bar->value();
            for(uint j=0; j<30; j++) {
                Tree->topLevelItem(i)->addChild(new QTreeWidgetItem(QStringList()<<QString::number(Value+j))); //Add 30 new children
            }
            break;
        }
    }
}

This way you have one slider to scroll the QTreeWidget and the second one to change content of expanded topLevelItem.

MKAROL
  • 316
  • 3
  • 11