PDA

View Full Version : Scroll-to-column in QTreeWidget?



dictoon
21st May 2013, 10:42
I have a QTreeWidget displaying a hierarchy of nodes. I'm successfully using QTreeWidget::scrollToItem() to make sure a given item is visible, however sometimes the item is so far on the right (being so deep in the hierarchy) that one needs to scroll the tree widget horizontally to make it actually appear. Is there a way (or a trick) to make a given column (0 in my case) of a given item visible, a scrollToColumn() kind of thing?

Santosh Reddy
21st May 2013, 14:09
Is there a way (or a trick) to make a given column (0 in my case) of a given item visible, a scrollToColumn() kind of thing?
You can use QTreeView::scrollTo(const QModelIndex & index, ScrollHint hint = EnsureVisible);
Example:


// Get the index of the item (ITEM-A) on 10th row 1st column
QModelIndex index = mTreeWidget->model()->index(9, 0); // Row 10, Column 1

// Get the index of the child of ITEM-A on Row 1, and 10th column.
index = index.child(0, 9); // Row 1, Column 10

// Scroll to item
mTreeWidget->scrollTo(index);

dictoon
21st May 2013, 18:03
Hey Santosh,

Thanks for your reply. I'm afraid I couldn't make it to work though. Here is my implementation based on your suggestion:


void compute_index(QTreeWidget* tree, QTreeWidgetItem* item, QModelIndex& index)
{
if (item->parent())
{
compute_index(tree, item->parent(), index);
index = index.child(item->parent()->indexOfChild(item), 0);
}
else
{
index = tree->model()->index(tree->indexOfTopLevelItem(item), 0);
}
}

// Later, given item and treeWidget:

QModelIndex index;
compute_index(treeWidget, item, index);
treeWidget->scrollTo(index);



The result is exactly the same as what I get using QTreeWidget::scrollToItem(): no horizontal scrolling is done to ensure the item is actually visible.

Franz

Santosh Reddy
22nd May 2013, 11:02
Try this, I have checked it works just fine.


QModelIndex computeModelIndex(QTreeWidgetItem * item, int column = 0)
{
QModelIndex index;

if(item == 0)
return index;

QTreeWidget * treeWidget = item->treeWidget();

if(treeWidget == 0)
return index;

QTreeWidgetItem * parent = item->parent();

if(parent)
return computeModelIndex(parent, 0).child(parent->indexOfChild(item), column);

return treeWidget->model()->index(treeWidget->indexOfTopLevelItem(item), 0);
}

//elsewhere
QModelIndex index = computeModelIndex(item, 9);
if(index.isValid())
mTreeWidget->scrollTo(index);

dictoon
23rd May 2013, 16:58
Hey Santosh,

Thanks again for taking the time to answer with detailed code.

I'm afraid I wasn't very clear on my problem, so I created a small test application (Windows, x64) that illustrates well the issue I'm trying to solve:



scrollToColumn-x64.zip (http://appleseedhq.net/stuff/scrollToColumn-x64.zip) (17 KB, assumes you have the Qt 5.0.2 DLLs lying around)
scrollToColumn-x64-standalone.zip (http://appleseedhq.net/stuff/scrollToColumn-x64-standalone.zip) (14 MB, includes all required Qt DLLs)
scrollToColumn-src.zip (http://appleseedhq.net/stuff/scrollToColumn-src.zip) (Qt Creator 5.0.2 project)


Start the application, then press the "Select Random Item" button at the bottom to select a random item in the tree widget. As you will notice, although the tree widget scrolls horizontally to the selected item, the actual text of the item isn't visible as it's too far on the right (due to the indentation). What I'm trying to do is to always make the text of the item visible.

(Note that, although the tree widget has two columns, only the first one (at index 0) is populated and this is the one I would like to make visible.)

Franz

dictoon
23rd May 2013, 21:12
I solved my problem by simply doing the following:


ui->treeWidget->scrollToItem(item);
const QRect r = ui->treeWidget->visualItemRect(item);
ui->treeWidget->horizontalScrollBar()->setValue(r.x());

Basically, I retrieve the horizontal position of the item within the viewport of the tree widget, then I adjust the horizontal scrollbar such that it aligns with the left of the item.

Thanks again Santosh for your time.

Franz