Results 1 to 6 of 6

Thread: QListWidget resize item to reproduce Windows behavior : Magical Number needed

  1. #1
    Join Date
    May 2013
    Posts
    321
    Thanks
    9
    Thanked 8 Times in 8 Posts
    Qt products
    Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Exclamation QListWidget resize item to reproduce Windows behavior : Magical Number needed

    Hi,
    Here my solution to reproduce the Windows behavior to have always the QListWidget filled in space (override of QStyledItemDelegate) :
    Qt Code:
    1. virtual QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const override
    2. {
    3. const int RightMargin = 15;
    4. const QSize ItemPadding = QSize( 6, 6 );
    5. QListWidget* ListWidget = static_cast< QListWidget* >( parent() );
    6. const int MaxWidth = ListWidget->viewport()->width() - RightMargin;
    7. const int ItemWidth = option.decorationSize.width() + ItemPadding.width();
    8. if( ItemWidth >= MaxWidth )
    9. return option.decorationSize + QSize( 0, option.fontMetrics.height() ) + ItemPadding;
    10. const int ItemHeight = option.decorationSize.height() + option.fontMetrics.height() + ItemPadding.height();
    11. const int NumItem = std::max( 1, MaxWidth / ItemWidth );
    12. const int NumRow = std::ceil( static_cast< float >( ListWidget->count() ) / static_cast< float >( NumItem ) );
    13. const bool ScrollbarVisible = ( NumRow * ItemHeight ) > ListWidget->viewport()->height();
    14. if( ScrollbarVisible )
    15. {
    16. const int PaddingOffset = ( NumItem >= ListWidget->count() ) ? 0 : ( MaxWidth - ( NumItem * ItemWidth ) ) / NumItem;
    17. return option.decorationSize + QSize( 0, option.fontMetrics.height() ) + ItemPadding + QSize( PaddingOffset, 0 );
    18. }
    19. else
    20. {
    21. // 3 pixels removed to avoid flickering when resize.
    22. const int NewMaxWidth = ListWidget->viewport()->width() - RightMargin - 3;
    23. const int NewNumItem = std::max( 1, NewMaxWidth / ItemWidth );
    24. const int PaddingOffset = ( NewNumItem >= ListWidget->count() ) ? 0 : ( NewMaxWidth - ( NewNumItem * ItemWidth ) ) / NewNumItem;
    25. return option.decorationSize + QSize( 0, option.fontMetrics.height() ) + ItemPadding + QSize( PaddingOffset, 0 );
    26. }
    27. }
    To copy to clipboard, switch view to plain text mode 
    This code compute the free space on the right based on the known item size and distribute in each item to always be filled on the width.
    All works fine but why this 3px magical number is needed to avoid flickering when the scrollbar is not visible ?
    If this magical number is not used one item always swap from one line to another when resize.
    Thanks
    Last edited by Alundra; 16th January 2016 at 04:24.

  2. #2
    Join Date
    May 2013
    Posts
    321
    Thanks
    9
    Thanked 8 Times in 8 Posts
    Qt products
    Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QListWidget resize item to reproduce Windows behavior : Magical Number needed

    Using RightMargin of 21 solve all issue apparently.

  3. #3
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QListWidget resize item to reproduce Windows behavior : Magical Number needed

    Using RightMargin of 21 solve all issue apparently.
    Which you should understand is just another magic number that is likely to change based on your screen resolution, font magnification, and / or default font. Change your screen magnification and I'll bet your code no longer works the same way.

  4. #4
    Join Date
    May 2013
    Posts
    321
    Thanks
    9
    Thanked 8 Times in 8 Posts
    Qt products
    Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QListWidget resize item to reproduce Windows behavior : Magical Number needed

    Here the actual code which is well reduced but still use the constant 20 :
    Qt Code:
    1. virtual QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const override
    2. {
    3. // Unused.
    4. DE_UNUSED( index );
    5.  
    6. // Constants.
    7. const int RightMargin = 20;
    8. const QSize ItemPadding = QSize( 6, 6 );
    9. const int ItemWidth = option.decorationSize.width() + ItemPadding.width();
    10.  
    11. // Get the list widget using the parent value.
    12. QListWidget* ListWidget = static_cast< QListWidget* >( parent() );
    13.  
    14. // Compute the max width and the row item count.
    15. const int MaxWidth = ListWidget->viewport()->width() - RightMargin;
    16. const int RowItemCount = std::max( 1, MaxWidth / ItemWidth );
    17.  
    18. // Cases where the padding offset is not needed.
    19. if( ( ItemWidth >= MaxWidth ) || ( RowItemCount >= ListWidget->count() ) )
    20. return option.decorationSize + QSize( 0, option.fontMetrics.height() ) + ItemPadding;
    21.  
    22. // Compute the padding offset and add in the item size to compensate of empty space.
    23. const int PaddingOffset = ( MaxWidth - ( RowItemCount * ItemWidth ) ) / RowItemCount;
    24. return option.decorationSize + QSize( PaddingOffset, option.fontMetrics.height() ) + ItemPadding;
    25. }
    To copy to clipboard, switch view to plain text mode 
    If a way to have it really better and still working good exists, i'm open to listen how solve that.

  5. #5
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: QListWidget resize item to reproduce Windows behavior : Magical Number needed

    The magic is likely some element(s) of the style's rendering of the widgets that you are not accounting for. You may be able to work the amount of "magic" required using the QStyle::pixelMetric() function and constants
    http://doc.qt.io/qt-4.8/qstyle.html#PixelMetric-enum

    The flickering is probably because the automatic scrollbar is being added and removed repeatedly because the size of the contained widget is changing around the scroll area's critical size. You need to be careful that the appearance of the scroll bar, which narrows the viewport, does not trigger a shrinking of the layout that causes the viewport to grow... Circular updates.

  6. #6
    Join Date
    May 2013
    Posts
    321
    Thanks
    9
    Thanked 8 Times in 8 Posts
    Qt products
    Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QListWidget resize item to reproduce Windows behavior : Magical Number needed

    The idea is easy, simply compensate the empty space on each item to use the whole space on the width but to remove this constant, it's not so easy.
    Using a little value to only have very little empty space you got bad result (flickering). The solution I give is the only one I found after lot of tests.
    Maybe a padding-left needed to solve completely, but then you have big margin on the left and right of the row.
    using :
    Qt Code:
    1. m_ListWidget->setStyleSheet( "QListView{ padding-left: 10px; }" );
    To copy to clipboard, switch view to plain text mode 
    I have to use this value to have 0 flickering (if the scrollbar is visible or not) :
    Qt Code:
    1. const int RightMargin = 28;
    To copy to clipboard, switch view to plain text mode 
    But the margin is not the same on the left and right, I have 10px on the left but more space on the right, 28px.
    For the case where no padding-left is set, I got also good visual without flickering using 18px for the RightMargin, which gives less empty space than 20px.
    That works very well but it's not centered, you have 0 empty space on the left and 18px empty space on the right and no solution found to have it centered...
    Last edited by Alundra; 19th January 2016 at 02:01.

Similar Threads

  1. Dynamically resize item of QListWidget
    By Alundra in forum Qt Programming
    Replies: 1
    Last Post: 5th January 2016, 23:20
  2. Replies: 1
    Last Post: 11th November 2015, 14:14
  3. QSplitter resize behavior
    By Alundra in forum Qt Programming
    Replies: 0
    Last Post: 5th June 2014, 22:25
  4. Strange resize behavior
    By Lykurg in forum Newbie
    Replies: 3
    Last Post: 9th January 2007, 14:56
  5. QListWidget selection behavior as in Windows XP
    By Levon Nikoghosyan in forum Qt Programming
    Replies: 1
    Last Post: 9th January 2007, 14:11

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.