web-dev-qa-db-fra.com

Comment maintenir le ratio d'aspect des widgets dans Qt?

Comment est-il possible de conserver le rapport hauteur/largeur des widgets dans Qt et qu’en est-il du centrage du widget?

31
Bleadof

Vous n'êtes pas obligé d'implémenter votre propre gestionnaire de disposition. Vous pouvez faire avec hériter de QWidget et réimplémenter

int QWidget::heightForWidth( int w ) { return w; }

rester carré. Cependant, heightForWidth() ne fonctionne pas sur les fenêtres de niveau supérieur sur X11, car apparemment le protocole X11 ne le supporte pas. En ce qui concerne le centrage, vous pouvez passer Qt::AlignCenter en tant que troisième paramètre de QBoxLayout::addWidget() ou cinquième paramètre de QGridLayout::addWidget().

Remarque: Dans les versions plus récentes de Qt au moins, QWidget n’a plus la valeur heightForWidth ou widthForHeight (elle ne peut donc pas être ignorée), et donc setWidthForHeight(true) ou setHeightForWidth(true)n’a d’effet que pour les descendants de QGraphicsLayout .

16
Marc Mutz - mmutz

La bonne réponse est de créer votre gestionnaire de disposition personnalisé. Cela est possible en sous-classant QLayout .

Méthodes à implémenter lors de la sous-classification de QLayout

void addItem (QLayoutItem * item);
Ajoute un élément à la mise en page.
int count () const;
Retourne le nombre d'articles.
QLayoutItem * itemAt (int index) const;
Retourne la référence de l'élément à l'index ou à 0 s'il n'y en a pas.
QLayoutItem * takeAt (int index);
Prend et renvoie un élément de la mise en page à partir de l'index ou renvoie 0 s'il n'en existe pas.
Qt :: Orientations expandDirections () const;
Renvoie les mises en page en développant les directions.
bool hasHeightForWidth () const;
Indique si la mise en page gère la hauteur pour le calcul de la largeur.
QSize minimumSize () const;
Renvoie la taille minimale des mises en page.
void setGeometry (const QRect & rect);
Définit la géométrie de la présentation et les éléments qu’elle contient. Ici, vous devez conserver les proportions et faire le centrage.
QSize sizeHint () const;
Retourne la taille préférée pour la mise en page.

Lectures complémentaires

8
Bleadof

Appeler resize() depuis resizeEvent() n'a jamais bien fonctionné pour moi. Au mieux, cela provoquera un scintillement lorsque la fenêtre est redimensionnée deux fois (comme vous l'avez déjà fait), au pire, une boucle infinie.

Je pense que le "bon" moyen de conserver un format d'image fixe consiste à créer une mise en page personnalisée. Vous devrez remplacer seulement deux méthodes, QLayoutItem::hasHeightForWidth() et QLayoutItem::heightForWidth().

5
dF.

Dans mon cas, remplacer heightForWidth () ne fonctionne pas. Et, pour quelqu'un, il pourrait être utile d'avoir un exemple concret d'utilisation de l'événement resize.

Dans la première sous-classe, qObjet pour créer un filtre. En savoir plus sur les filtres d'événement.

class FilterObject:public QObject{
public:
    QWidget *target = nullptr;//it holds a pointer to target object
    int goalHeight=0;
    FilterObject(QObject *parent=nullptr):QObject(parent){}//uses QObject constructor
    bool eventFilter(QObject *watched, QEvent *event) override;//and overrides eventFilter function
};

Puis la fonction eventFilter. Son code doit être défini en dehors de la définition de FilterObject pour éviter les avertissements. Merci à cette réponse.

bool FilterObject::eventFilter(QObject *watched, QEvent *event) {
    if(watched!=target){//checks for correct target object.
        return false;
    }
    if(event->type()!=QEvent::Resize){//and correct event
        return false;
    }

    QResizeEvent *resEvent = static_cast<QResizeEvent*>(event);//then sets correct event type

    goalHeight = 7*resEvent->size().width()/16;//calculates height, 7/16 of width in my case
    if(target->height()!=goalHeight){
        target->setFixedHeight(goalHeight);
    }

    return true;
};

Et ensuite, dans le code principal, créez FilterObject et définissez-le comme écouteur EventFilter comme objet cible. Merci à cette réponse.

FilterObject *filter = new FilterObject();
QWidget *targetWidget = new QWidget();//let it be target object
filter->target=targetWidget;
targetWidget->installEventFilter(filter);

Désormais, le filtre recevra tous les événements de targetWidget et définira la hauteur correcte lors d'un événement de redimensionnement.

0
PolyGlot