Comment maintenir le ratio d'aspect des widgets dans Qt?
-
19-08-2019 - |
Question
Comment est-il possible de conserver le rapport hauteur / largeur des widgets dans Qt et qu’en est-il du centrage du widget?
La solution
Vous n'avez pas à 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 les plus complètes 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 le cinquième paramètre de QGridLayout :: addWidget ()
.
Remarque: dans les versions les plus récentes de Qt, QWidget ne dispose plus du heightForWidth
ni du widthForHeight
(ils ne peuvent donc pas être remplacés). et par conséquent setWidthForHeight (true)
ou setHeightForWidth (true)
n'a d'effet que sur les descendants de QGraphicsLayout .
Autres conseils
La bonne réponse est de créer votre gestionnaire de disposition personnalisé. C’est possible en QLayout .
Méthodes à implémenter lors de la sous-classification de QLayout
- annulation d'un addItem (élément QLayoutItem *);
- Ajoute un élément à la présentation.
- int count () const;
- Renvoie le nombre d'éléments.
- QLayoutItem * itemAt (index int) const;
- Renvoie 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 retourne un élément de la mise en page à partir de l'index ou renvoie 0 s'il n'y en a aucun.
- Qt :: Orientations expandDirections () const;
- Renvoie les dispositions développant les directions.
- bool hasHeightForWidth () const;
- Indique si la présentation gère la hauteur pour le calcul de la largeur.
- QSize minimumSize () const;
- Renvoie la taille minimale des dispositions.
- void setGeometry (const QRect & rect);
- Définit la géométrie de la mise en page et des éléments qu'elle contient. Ici, vous devez conserver les proportions et faire le centrage.
- QSize sizeHint () const;
- Renvoie la taille préférée pour la mise en page.
Lectures supplémentaires
L'appel de 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 ), au pire une boucle infinie.
Je pense que le " correct " Pour maintenir un rapport hauteur / largeur fixe, vous pouvez créer une mise en page personnalisée. Vous devrez remplacer seulement deux méthodes, QLayoutItem :: hasHeightForWidth ()
et QLayoutItem :: heightForWidth ()
.
Dans mon cas, remplacer heightForWidth () ne fonctionne pas. Et, pour quelqu'un, il pourrait être utile d'avoir un exemple d'utilisation de l'événement de redimensionnement.
Dans la première sous-classe qObject 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;
};
Ensuite, dans le code principal, créez FilterObject et définissez-le comme écouteur EventFilter en tant qu'objet cible. Grâce à cette réponse.
FilterObject *filter = new FilterObject();
QWidget *targetWidget = new QWidget();//let it be target object
filter->target=targetWidget;
targetWidget->installEventFilter(filter);
Maintenant, le filtre recevra tous les événements du cibleWidget et définira la hauteur correcte lors du redimensionnement.