Important: Please read the Qt Code of Conduct -

[Solved] QTreeWidget and checking if it's vertical scroll bar is visible

  • Dear Qt programmers,

    I've a problem checking if a QTreeWidget has a scroll bar or not. I know where the problem is but I don't know how to solve it the proper way. Let's get to the point.

    I have a refreshUI() method in my class which looks more or less like below (I've cut out the unnecessary parts of it):
    void MyClass::refreshUI() {
    QTreeWidget* tw = _ui->treeWidget;
    while(tw->topLevelItemCount() > 0) {
    delete tw->takeTopLevelItem(0);
    QString longestValueString;
    for(int i = 0; i < accounts.count(); ++i) {
    longestString = "";
    Account* a = accounts[i];
    QTreeWidgetItem* i = new QTreeWidgetItem;
    i->setText(0, a->name);
    if(longestString.length() < a->someString.length()) {
    longestString = a->someString;
    i->setText(1, a->someString);
    int scrollBarWidth = 0;
    // I always get false below.
    if(tw->verticalScrollBar()->isVisible()) {
    scrollBarWidth = tw->verticalScrollBar()->width();
    tw->setColumnWidth(0, tw->width() - tw->fontMetrics().boundingRect(longestString).width() - 100);
    tw->setColumnWidth(1, tw->width() - tw->columnWidth(0) - scrollBarWidth);

    This method is executed after my QList<Account*> changes. As you can see, right after adding items to my QTreeWidget I'm checking if a vertical scroll bar appeared (tree widget is set to Qt::ScrollBarAsNeeded). If it has, it'd like to change the width of the second (last) column accordingly. Unfortunately, as stated in the commented line in the code, I always get a false result when I'm checking if the scroll bar is visible.

    What I'm guessing is that the QTreeWidget "doesn't know" yet that it has to show a scroll bar when I'm checking if the scroll bar is visible. I thought that making itself repaint() before the check will make it find it out, but of course it didn't (I've put tw->repaint(); between lines 18 and 19).

    Is there any way I can force my QTreeWidget to add a scroll bar right after inserting items to it? Please don't tell me I need to subclass it to make it work. I was thinking about a timer with a 10ms delay (or whatever time is needed to repaint my application) that would launch the 4 lines of code (excluding the '}') responsible for column resizing. That seems to be nasty though. Any better ways to achieve it?

    Thank you in advance for your suggestions.

  • I setup a timer slot to relsize tableview cell width,so you can do this also.

  • noregister, I also thought about that but I'm looking for an elegant solution.

    Anyway, I've been able to track the problem a little bit deeper. My refreshUI() method is being run on application startup and also when switching between tabs in my application. One of the tabs is showing this QTreeWidget (first tab you see after starting the app). So what I've noticed now is that this tab is not yet visible when I'm checking for scroll bar visibility. refreshUI() method is launched before QMainWindow::show() in the first case and with a signal/slot connection (pseudocode):
    @(QTabWidget, SIGNAL(currentChanged(int)), QTreeWidget, SLOT(onCurrentTabChanged(int)))@
    in the second. It seems that the above signal is emitted before new widget is set to visible on the QTabWidget.

    Should I just manually set it to be visible when entering refreshUI()?

  • you can invoke the SLOT after add new widget by "QTimer::singleShot":

    In my application ,I invoke SLOT after setModel of tableview to adjust table cell width.

  • Solved it in a different way. I "reimplemented" paintEvent() of my QMainWindow class and I'm checking there for visibility of the tab page which contains the QTreeWidget. If it's visible then I adjust column width. I guess that's better than using timers.

Log in to reply