thumbnails example improved for the use case of having many items
This commit is contained in:
parent
fe98439bd6
commit
f654da28c0
|
@ -16,11 +16,14 @@
|
||||||
#include <QskObjectCounter.h>
|
#include <QskObjectCounter.h>
|
||||||
#include <QskPushButton.h>
|
#include <QskPushButton.h>
|
||||||
#include <QskScrollArea.h>
|
#include <QskScrollArea.h>
|
||||||
|
#include <QskQuick.h>
|
||||||
#include <QskWindow.h>
|
#include <QskWindow.h>
|
||||||
|
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
|
#define HIDE_NODES 1
|
||||||
|
|
||||||
const int gridSize = 20;
|
const int gridSize = 20;
|
||||||
const int thumbnailSize = 150;
|
const int thumbnailSize = 150;
|
||||||
|
|
||||||
|
@ -65,10 +68,21 @@ class Thumbnail : public QskPushButton
|
||||||
Thumbnail( const QColor& color, int shape, QQuickItem* parentItem )
|
Thumbnail( const QColor& color, int shape, QQuickItem* parentItem )
|
||||||
: QskPushButton( parentItem )
|
: QskPushButton( parentItem )
|
||||||
{
|
{
|
||||||
using namespace SkinnyShapeFactory;
|
|
||||||
|
|
||||||
const QSizeF size( thumbnailSize, thumbnailSize );
|
const QSizeF size( thumbnailSize, thumbnailSize );
|
||||||
|
|
||||||
|
setGraphic( thumbnailGraphic( color, shape, size ) );
|
||||||
|
setFixedSize( size );
|
||||||
|
|
||||||
|
setFlat( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QskGraphic thumbnailGraphic( const QColor& color,
|
||||||
|
int shape, const QSizeF& size ) const
|
||||||
|
{
|
||||||
|
const auto path = SkinnyShapeFactory::shapePath(
|
||||||
|
static_cast< SkinnyShapeFactory::Shape >( shape ), size );
|
||||||
|
|
||||||
QskGraphic graphic;
|
QskGraphic graphic;
|
||||||
|
|
||||||
QPen pen( Qt::black, 3 );
|
QPen pen( Qt::black, 3 );
|
||||||
|
@ -80,13 +94,10 @@ class Thumbnail : public QskPushButton
|
||||||
painter.setPen( pen );
|
painter.setPen( pen );
|
||||||
painter.setBrush( color );
|
painter.setBrush( color );
|
||||||
|
|
||||||
painter.drawPath( shapePath( static_cast< Shape >( shape ), size ) );
|
painter.drawPath( path );
|
||||||
painter.end();
|
painter.end();
|
||||||
|
|
||||||
setGraphic( graphic );
|
return graphic;
|
||||||
setFixedSize( size );
|
|
||||||
|
|
||||||
setFlat( true );
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -104,7 +115,67 @@ class IconGrid : public QskLinearBox
|
||||||
for ( int row = 0; row < gridSize; row++ )
|
for ( int row = 0; row < gridSize; row++ )
|
||||||
( void ) new Thumbnail( randomColor(), randomShape(), this );
|
( void ) new Thumbnail( randomColor(), randomShape(), this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HIDE_NODES
|
||||||
|
/*
|
||||||
|
When having too many nodes, the scene graph becomes horribly slow.
|
||||||
|
So we explicitely hide all items outside the visible area
|
||||||
|
( see updateVisibilities below ) and make use of the DeferredUpdate and
|
||||||
|
CleanupOnVisibility features of QskQuickItem.
|
||||||
|
*/
|
||||||
|
setSize( sizeConstraint() );
|
||||||
|
updateLayout(); // so that every item has its initial geometry
|
||||||
|
|
||||||
|
for ( int i = 0; i < count(); i++ )
|
||||||
|
{
|
||||||
|
if ( auto item = qobject_cast< QskControl* > ( itemAtIndex( i ) ) )
|
||||||
|
{
|
||||||
|
// to support the optimizations in ScrollArea::updateVisibilities
|
||||||
|
item->setLayoutHint( RetainSizeWhenHidden, true );
|
||||||
|
item->setVisible( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HIDE_NODES
|
||||||
|
void updateVisibilities( const QRectF& viewPort )
|
||||||
|
{
|
||||||
|
if ( !isEmpty() && viewPort != m_viewPort )
|
||||||
|
{
|
||||||
|
setItemsVisible( m_viewPort, false );
|
||||||
|
setItemsVisible( viewPort, true );
|
||||||
|
|
||||||
|
m_viewPort = viewPort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setItemsVisible( const QRectF& rect, bool on )
|
||||||
|
{
|
||||||
|
const int dim = dimension();
|
||||||
|
|
||||||
|
// we know, that all items have the same size
|
||||||
|
const auto itemSize = qskItemSize( itemAtIndex( 0 ) );
|
||||||
|
|
||||||
|
const int rowMin = rect.top() / ( itemSize.height() + spacing() );
|
||||||
|
const int rowMax = rect.bottom() / ( itemSize.height() + spacing() );
|
||||||
|
|
||||||
|
const int colMin = rect.left() / ( itemSize.width() + spacing() );
|
||||||
|
const int colMax = rect.right() / ( itemSize.height() + spacing() );
|
||||||
|
|
||||||
|
for ( int row = rowMin; row <= rowMax; row++ )
|
||||||
|
{
|
||||||
|
for ( int col = colMin; col <= colMax; col++ )
|
||||||
|
{
|
||||||
|
if ( auto item = itemAtIndex( row * dim + col ) )
|
||||||
|
item->setVisible( on );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF m_viewPort;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScrollArea : public QskScrollArea
|
class ScrollArea : public QskScrollArea
|
||||||
|
@ -129,6 +200,29 @@ class ScrollArea : public QskScrollArea
|
||||||
setBoxShapeHint( HorizontalScrollHandle, 8 );
|
setBoxShapeHint( HorizontalScrollHandle, 8 );
|
||||||
|
|
||||||
setFlickRecognizerTimeout( 300 );
|
setFlickRecognizerTimeout( 300 );
|
||||||
|
|
||||||
|
connect( this, &QskScrollView::scrollPosChanged,
|
||||||
|
this, &ScrollArea::updateVisibilities );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void geometryChanged( const QRectF& newRect, const QRectF& oldRect ) override
|
||||||
|
{
|
||||||
|
QskScrollArea::geometryChanged( newRect, oldRect );
|
||||||
|
updateVisibilities();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateVisibilities()
|
||||||
|
{
|
||||||
|
#if HIDE_NODES
|
||||||
|
const auto box = static_cast< IconGrid* >( scrolledItem() );
|
||||||
|
if ( box )
|
||||||
|
{
|
||||||
|
const QRectF viewPort( scrollPos(), viewContentsRect().size() );
|
||||||
|
box->updateVisibilities( viewPort );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -153,6 +247,8 @@ int main( int argc, char* argv[] )
|
||||||
This example also shows, that blocking of the scene graph node creation
|
This example also shows, that blocking of the scene graph node creation
|
||||||
( QskControl::DeferredUpdate + QskControl::CleanupOnVisibility )
|
( QskControl::DeferredUpdate + QskControl::CleanupOnVisibility )
|
||||||
could be improved to also respect being inside the window or a clip region.
|
could be improved to also respect being inside the window or a clip region.
|
||||||
|
To have a similar effect with what is possible today, the code
|
||||||
|
explicitely hide/show(s) the buttons out/inside the viewport.
|
||||||
|
|
||||||
But here we only want to demonstrate how QskScrollArea works.
|
But here we only want to demonstrate how QskScrollArea works.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue