Results 1 to 19 of 19

Thread: QListWidget in a tab not scrolling on setCurrentRow()

  1. #1
    Join Date
    Jul 2007
    Posts
    21
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default QListWidget in a tab not scrolling on setCurrentRow()

    Using Qt 4.2.1/Linux/Eclipse Europa with CDT and Qt plugins.

    My application needs a font selection dialog box that restricts available fonts to fixed pitch, non-symbol fonts. The application only displays with one font but you can change which. So, the font selection dialog has a QListWidget of suitable fonts with the application's current font already selected in the list.

    My first cut was a Designer generated QDialog with a QListWidget and other necessary controls. I populated the list by filtering a QFontDatabase in my QDialog constructor. I added a member to set the selected font. Iterated the list for the one with the same family name and:

    Qt Code:
    1. ui.fontList->setCurrentRow(row);
    2. ui.fontList->item(row)->setSelected(true);
    To copy to clipboard, switch view to plain text mode 

    That all works nicely, the item is selected and is visible (scrolled into view) in the QListWidget. I suspect there's a redundancy there though but it's harmless at this point.

    I decided to move the font selection from a dedicated dialog to a tab on another configuration dialog. I copied the code and repeated the Designer layout and very carefully verified everything was copied and fixed up properly. This time, the correct item is selected but, it is not scrolled into view unless it was in the top visible items. Just for kicks I added a scrollToBottom() after the above and it had no effect. Remember the correct item is selected so I know execution is passing through this but I single stepped it and confirmed it anyway.

    As far as I can tell the only difference is that the QListWidget's parent has gone from being a QDialog to being a QWidget in a QTabWidget.

    Thanks for any advice/suggestions.

  2. #2
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    You can try this after you set the current row:
    Qt Code:
    1. QModelIndex index = ui.fontList->currentIndex();
    2. ui->fontList->scrollTo(index, QAbstractItemView::EnsureVisible);
    To copy to clipboard, switch view to plain text mode 

    Also, you can use QListWidget::scrollToItem:
    Qt Code:
    1. QListWidgetItem item = ui.fontList->item(row);
    2. ui->fontList->scrollToItem(item, QAbstractItemView::EnsureVisible);
    To copy to clipboard, switch view to plain text mode 

    Regards
    Last edited by marcel; 22nd July 2007 at 08:55.

  3. The following user says thank you to marcel for this useful post:

    maird (22nd July 2007)

  4. #3
    Join Date
    Jul 2007
    Posts
    21
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    Marcel: Many thanks for the suggestions but neither worked. I had tried scrollToItem(). I didn't mention it because scrollToBottom() showed the same behaviour - sorry.

    I'm going to try to reproduce this with a simple example in a clean project. In the meantime, I'd be grateful for any other suggestions.

    FWIW, there were a couple of errors in the code you posted. I'll correct them for anyone reading later. In line 2 of the first example ui is not a pointer and the operator to access fontList should be . rather than ->

    Qt Code:
    1. QModelIndex index = ui.fontList->currentIndex();
    2. ui.fontList->scrollTo(index, QAbstractItemView::EnsureVisible);
    To copy to clipboard, switch view to plain text mode 

    In the second one QListWidget::item() returns a pointer to a QListWidgetItem

    Qt Code:
    1. QListWidgetItem* item = ui.fontList->item(row);
    2. ui.fontList->scrollToItem(item, QAbstractItemView::EnsureVisible);
    To copy to clipboard, switch view to plain text mode 

  5. #4
    Join Date
    Jul 2007
    Posts
    21
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    I cannot reproduce it with a new, clean project and the simplest implementation I can come up with and using the following to select the item:

    Qt Code:
    1. ui.listWidget->setCurrentRow(row);
    2. ui.listWidget->item(row)->setSelected(true);
    To copy to clipboard, switch view to plain text mode 

    Therefore I assume the problem case is a side-effect of something else in my real project. I'll use the test project that works as a reference and fix it in the real project.

    Marcel: many thanks for the suggestions.

  6. #5
    Join Date
    Jul 2007
    Posts
    21
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    Whoa there. Scratch my previous comment. I can reproduce it with a simple sample.

    Here's how I did it:

    1. Create a main window project
    2. Add a menu (File)
    3. Add Test and Exit items to the File menu
    4. Connect File->Exit to the main window class close()
    5. Create a dialog with an associated class
    6. Add a tab control to the dialog
    7. Add a QListWidget to the tab
    8. Modify the constructor of the dialog class to populate the list
    9. Add a member function to the class that takes a QString, searches for it in the QListWidget and setCurrentItem() then setSelected(true)
    10. Create a slot for File->Test in the main window class
    11. Make the member create an instance of the dialog class
    12. Call the dialog class member that selects an item, passing an item QString that would not normally be visible when the dialog shows
    13. exec() the dialog
    14. Build and run - Use File->Test, the item is selected and is visible
    15. Shutdown program
    16. Change the layout of the tab widget in the dialog to Grid
    17. Build and run - The item is selected but is not visible


    If the tab layout had no layout the problem is not observed! That makes no sense as a cause but it happens as soon as I set the layout of the tab widget to grid. I didn't try any other layouts. Bug?

    NB: Using Qt 4.2.1 on x86_64 Linux, Eclipse + CDT + Qt for project and build.

    If someone can try to reproduce it with a later Qt version using the instructions above I'd appreciate the data.

  7. #6
    Join Date
    Jul 2007
    Posts
    21
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    BTW, if the QListWidget is a child of a QDialog that has a grid layout the problem is not observed. IOW, it's only in a grid layout tab widget (so far).

  8. #7
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    So many instructions ...
    Why don't you posted the code instead?
    Would have helped...

    Regards

  9. #8
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    Quote Originally Posted by maird View Post
    ...IOW, it's only in a grid layout tab widget (so far).
    What about the layout of the dialog in which the tab widget is.
    What layout did you set for it?

    Regards

  10. #9
    Join Date
    Jul 2007
    Posts
    21
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    I did some other testing. If I leave the tab with no layout and add a QGridLayout to the tab then put the QListWidget in that QGridLayout it works OK. If I then give the QTabWidget grid layout (remember it still contains a QGridLayout containing a QListWidget) then the problem appears again. Bizarre!

  11. #10
    Join Date
    Jul 2007
    Posts
    21
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    Quote Originally Posted by marcel View Post
    What about the layout of the dialog in which the tab widget is.
    What layout did you set for it?
    It happens when the containing dialog has no layout and when it has grid layout.

    I'll post the code, I'm new here. Is it OK to post the whole sample project, e.g. as a tarball attachment?

  12. #11
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    Quote Originally Posted by maird View Post
    I'll post the code, I'm new here. Is it OK to post the whole sample project, e.g. as a tarball attachment?
    Sure. Even better.

    Regards

  13. #12
    Join Date
    Jul 2007
    Posts
    21
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    Attached listWidgetTest.tar.bz2 containing a clean sample project that reproduces the problem.

    It's a main window app with a Test menu.

    • Test->Exit terminates the program
    • Test->Dialog shows a QDialog selecting an item and scrolling to it
    • Test->Tabs Bad shows a dialog with a tab control with a grid layout selecting an item but not scrolling to it
    • Test->Tabs Good shows a dialog with a tab control that has no layout selecting an item and scrolling to it


    There's a QDialog derived class for all of the dialog forms and they all use the same implementation to populate the list and select an item. Thanks for your time Marcel.
    Attached Files Attached Files

  14. #13
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    Yes, I can confirm the behavior.
    If you put the list in a tab, and set to the tab widget any kind of layout, then auto scrolling will not work.

    Debugging scrollToItem shows that the list widget actually thinks that the target item is already visible and it just updates the item rect. It does not adjust the scrollbars, as it should.

    Perhaps the scrollbars should be adjusted manually?

    I think this requires a little more research.

    Regards

  15. The following user says thank you to marcel for this useful post:

    maird (22nd July 2007)

  16. #14
    Join Date
    Jul 2007
    Posts
    21
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    Marcel: Thanks for the confirmation. I had tried getting the QListWidget's vertical scrollbar and setting the position on it. That had no effect either but I think I'll try it again in this simple project.

  17. #15
    Join Date
    Jul 2007
    Posts
    21
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    I tried using the scrollbar directly and that didn't work either. I added the following after selecting the found item:

    Qt Code:
    1. QScrollBar* sb = ui.listWidget->verticalScrollBar();
    2. int min = sb->minimum();
    3. int max = sb->maximum();
    4. int range = max - min;
    5.  
    6. // Take the found row as a fraction of the count
    7. int r = row + 1;
    8. int c = ui.listWidget->count();
    9. int v = (100 * r) / c;
    10.  
    11. // Move to that fraction of the scrollbar range
    12. int p = (range * v) / 100;
    13. p += min;
    14. sb->setValue(p);
    To copy to clipboard, switch view to plain text mode 

  18. #16
    Join Date
    Jul 2007
    Posts
    21
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    I single stepped the scrollbar code above and was surprised to find the min and max values for the scrollbar are zero. The code above (and anything that assumes it can scroll with QScrollBar::setValue()) will not scroll at all. That's probably why "the list widget thinks the item is already visible" in your debugging.

    But the scrollbar visually seen on the dialog has a non-zero range and works to scroll the list. So, I added the following between lines 1 and 2:

    Qt Code:
    1. sb->setRange(0, ui.listWidget->count() - 1);
    To copy to clipboard, switch view to plain text mode 

    Then the sb->setValue(p); works to show the selected item. So, I figured just use setRange() in the constructor after populating the list and the normal setCurrentItem()/setSelected(true) will work as expected. Nope, the scrollbar range is 0, 0 by the time you get to the function that selects an item.

    I suppose I can workaround it by setting the scrollbar range before trying to find and select anything in it. I think there's a Qt bug here.

  19. #17
    Join Date
    Jul 2007
    Posts
    21
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    I instrumented the loop that finds the item to be selected and looked at the scrollbar range after every operation. It is 0, 20 at the start and stays that way until:

    Qt Code:
    1. ui.listWidget->setCurrentRow(row)
    To copy to clipboard, switch view to plain text mode 

    Across that function call the scrollbar range changes to 0, 0. Setting the scrollbar range anywhere before calling setCurrentRow() isn't a workaround. So, I save the scrollbar range on entry to the function that selects an item and set the range to the saved values after using setCurrentRow(). I thought it would be a simple matter of using QListWidget::scrollToItem() to scroll the item into view but that doesn't work. I'll need to use QScrollBar::setValue().

    Cool bug!

  20. #18
    Join Date
    Jul 2007
    Posts
    21
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    This is my workaround:

    Qt Code:
    1. void listTab::changeTo(QString& it)
    2. {
    3. bool funkysb;
    4. int min;
    5. int max;
    6. int range;
    7. int row;
    8. int r;
    9. int c = ui.listWidget->count();
    10. int v;
    11. QString number;
    12.  
    13. sb = ui.listWidget->verticalScrollBar();
    14. min = sb->minimum();
    15. max = sb->maximum();
    16. range = max - min;
    17.  
    18. funkysb = ((range == 0) && (c != 0));
    19. if (funkysb)
    20. {
    21. // The scrollbar range is zero and the control contains
    22. // items, set the scroll range to something useful
    23. min = 0;
    24. max = c - 1;
    25. range = max - min;
    26. sb->setRange(min, max);
    27. }
    28.  
    29. // Find the specified number in the list
    30. for (row = 0; row < c; row++)
    31. {
    32. number = ui.listWidget->item(row)->text();
    33.  
    34. if (number == it)
    35. {
    36. // Make it the current selection
    37. // This resets the scrollbar range to 0,0 if the
    38. // list is in a tab widget with a layout
    39. ui.listWidget->setCurrentRow(row);
    40. ui.listWidget->item(row)->setSelected(true);
    41.  
    42. // Reset the scrollbar range if we have funkiness
    43. r = sb->maximum() - sb->minimum();
    44. if (funkysb && (r != range))
    45. {
    46. sb->setRange(min, max);
    47.  
    48. // Scroll to the item
    49. sb = ui.listWidget->verticalScrollBar();
    50. r = (row + 1) * range;
    51. c = ui.listWidget->count();
    52. v = r / c;
    53. if (r % c)
    54. {
    55. v++;
    56. }
    57. sb->setValue(v);
    58. }
    59. break;
    60. }
    61. }
    62. }
    To copy to clipboard, switch view to plain text mode 

  21. #19
    Join Date
    Jul 2007
    Posts
    21
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QListWidget in a tab not scrolling on setCurrentRow()

    This never ends. The workaround works (it can be made simpler) but it only works if the QListWidget has whatever default size designer would give it in a grid control with a layout and no other controls! As soon as you change it from the default size either by re-sizing the tab control in designer or by adding controls to the tab driving the scrollbar stops working. The scrollbar works but it doesn't scroll as far as you expect so that the last few items can't be scrolled to. The number you can't reach depends on how far the control is from this "preferred" size.

Similar Threads

  1. QGraphicsView scrolling problem with 4.3.0
    By hb in forum Qt Programming
    Replies: 8
    Last Post: 30th August 2007, 23:18
  2. Replies: 13
    Last Post: 15th December 2006, 12:52

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.