Bienvenue sur le forum !

Si vous souhaitez rejoindre la communauté, cliquez sur l'un de ces boutons !

Qt 5 : 5.7.1 - Qt Creator : 4.2.0 - Qt Installer : 2.0.3 - JOM : 1.1.2 - Qt Build suite : 1.7.0 - VS Qt 5 : 2.0.0

FlowLayout et miminum height dynamique

Bonjour,

J'ai besoin d'utilisé un FlowLayout en ce moment. J'ai donc repris le code de cet objet à partir de l'exemple fournit pat Qt.

Mon soucis est de forcer dynamiquement un minimum height au widget manageant le flowLayout en fonction de son width.

Comme vous avez pu le remarquer dans l'exemple fournit pas Qt, lorsque qu'on resize le widget, en jouant avec le coin, il arrivent que les boutons disparaissent car la fonction minimunSize() surchargée dans la classe FlowLayout retourne une taille "expanded" à partir des tailles minimales des items qu'il gère.

J'ai essayé de rajouter une ligne de code dans cette fonction pour forcer le height.
Le remède semble pire que le mal car cela n'est pas dynamique.
la fonction n'est en effet appelée que quelque fois au début de l'affichage et non à chaque redimensionnement !
QSize FlowLayout::minimumSize() const
{
QSize size;
QLayoutItem *item;
foreach (item, itemList)
size = size.expandedTo(item->minimumSize());

size.rheight() = this->heightForWidth( size.width() ) ; //code ajouté mais BOF !!

size += QSize(2*margin(), 2*margin());
return size;
}
Si je n'arrive pas à gérer dynamiquement le heigth, j'aurais toujours la possibilité d'utiliser une solution avec une QScrollArea à laquelle je passerai un widget ayant un FlowLayout et en indiquant que le widget puisse se redimensionner en utilisant la fonction setWidgetResizable.

Pour mes test, j'ai été direct modifier le code de l'exemple dans le fichier window.cpp ( dans /examples/layouts/flowlayout )
Window::Window()
{
FlowLayout *flowLayout = new FlowLayout;
flowLayout->addWidget(new QPushButton(tr("Short")));
flowLayout->addWidget(new QPushButton(tr("Longer")));
flowLayout->addWidget(new QPushButton(tr("Different text")));
flowLayout->addWidget(new QPushButton(tr("More text")));
flowLayout->addWidget(new QPushButton(tr("Even longer button text")));

setWindowTitle(tr("Flow Layout"));

QScrollArea *scroll ;
QHBoxLayout *layout_gen ;
QWidget *widget ;

widget = new QWidget ;
widget->setLayout( flowLayout ) ;

scroll = new QScrollArea ;
scroll->setWidget( widget ) ;
scroll->setWidgetResizable( true ) ;

layout_gen = new QHBoxLayout( this ) ;
layout_gen->addWidget( scroll ) ;

this->resize( 300, 200 ) ;
}
Si quelqu'un à une solution pour mon soucis ... grand merci !

Réponses

  • J'ai modifié encore un peu le code de windows.cpp de l'exemple flowLayout, afin d'avoir une espèce de minimun height dynamique. J'ai viré la QScrollArea car je n'ai pas réussi à lui faire prendre en compte le minimumSize du flowLayout du widget ( passé par setWidget).

    Cette fois j'ai juste utilisé un QGroupeBox et surtout surchargé la fonction resizeEvent pour utilisé ma fonction force_old_size.
    Window::Window()
    {
    FlowLayout *flowLayout = new FlowLayout;

    flowLayout->addWidget(new QPushButton(tr("Short")));
    flowLayout->addWidget(new QPushButton(tr("Longer")));
    flowLayout->addWidget(new QPushButton(tr("Different text")));
    flowLayout->addWidget(new QPushButton(tr("More text")));
    flowLayout->addWidget(new QPushButton(tr("Even longer button text")));

    setWindowTitle(tr("Flow Layout"));

    /* nécessaire si l'objet gère directement le flowLayout pour que le minimumSize soit pris en compte */
    flowLayout->setSizeConstraint( QLayout::SetMinimumSize ) ;

    // Ajout des boutons dans un QGroupBox
    QGroupBox *gb = new QGroupBox ;
    gb->setLayout( flowLayout ) ;

    QHBoxLayout *lay = new QHBoxLayout( this ) ;
    lay->addWidget( gb ) ;
    /* nécessaire pour que le minimumSize soit pris en compte */
    lay->setSizeConstraint( QLayout::SetMinimumSize ) ;
    }

    void Window::resizeEvent( QResizeEvent *event )
    {
    bool breaking ;

    /* Si le layout de l'objet est un FlowLayout (cas : pas de QGroupBox utilisé dans le constructeur) */
    breaking = this->force_old_size( this, event->oldSize() ) ;

    if ( breaking == false )
    {

    foreach ( QObject *obj, this->children() )
    {
    breaking = this->force_old_size( qobject_cast<QWidget *>( obj ), event->oldSize() ) ;

    if ( breaking == true )
    break ;
    }
    }

    if ( breaking == false )
    QWidget::resizeEvent( event ) ;

    }

    bool Window::force_old_size( QWidget *widget, QSize old_size )
    {
    bool retour ;

    retour = false ;

    if ( widget != 0 && qobject_cast<FlowLayout *>( widget->layout() ) != 0 )
    {
    if ( widget->height() < widget->heightForWidth( widget->width() ) )
    {
    this->resize( old_size ) ;

    retour = true ;
    }
    }

    return retour ;
    }
    Cela marchote !
    Quand on resize et que le height effectif est plus petit que le height minimum retourné par le heightForWidth, le widget Window retrouvera sa taille d'avant le resize mais seulement après qu'on ai relâché la souris !! Effet étrange et moyen, qui ne simule pas vraiment un mimumSize dynamique!

    Je vois plusieurs problème :
    - utilisation intempestive du qobject_cast (j'ai du ajouter la macro Q_OBJECT à FlowLayout)
    - Cela marchote, c'est moche
    - Si un développeur tiers utilise l'objet Window et le met dans une QDialog (via un QGridLayout par ex ), on retrouve le problème de disparition des boutons, et s'il oublie d'utiliser QLayout::setSizeConstraint( QLayout::SetMinimumSize ), le minimumSize du FlowLayout n'est plus pris en compte (normale en fait ) !

    Je poursuis mes investigations sur l'utilsation de layout ayant un height dépendant du width.
    Si vous avez des éclaircissements je suis prenneur

    Bonne soirée A+
Connectez-vous ou Inscrivez-vous pour répondre.