Come mantenere le proporzioni dei widget in Qt?
-
19-08-2019 - |
Domanda
Come è possibile mantenere le proporzioni dei widget in Qt e che dire del centrare il widget?
Soluzione
Non è necessario implementare il proprio gestore di layout. Puoi fare con l'eredità di QWidget
e la reimplementazione
int QWidget::heightForWidth( int w ) { return w; }
per rimanere quadrati. Tuttavia, heightForWidth ()
non funziona su finestre di livello superiore su X11, poiché apparentemente il protocollo X11 non lo supporta. Per quanto riguarda il centraggio, è possibile passare Qt :: AlignCenter
come terzo parametro di QBoxLayout :: addWidget ()
o il quinto parametro di QGridLayout :: addWidget ()
.
Nota: almeno nelle versioni più recenti di Qt, QWidget non ha più heightForWidth
o widthForHeight
(quindi non possono essere sostituiti) , e quindi setWidthForHeight (true)
o setHeightForWidth (true)
ha effetto solo per i discendenti di QGraphicsLayout .
Altri suggerimenti
La risposta giusta è creare il tuo gestore di layout personalizzato. Ciò è possibile effettuando la sottoclasse di QLayout .
Metodi da implementare durante la sottoclasse di QLayout
- void addItem (elemento QLayoutItem *);
- Aggiunge l'elemento al layout.
- int count () const;
- Restituisce il conteggio degli articoli.
- QLayoutItem * itemAt (int index) const;
- Restituisce il riferimento dell'oggetto all'indice o 0 se non ce n'è.
- QLayoutItem * takeAt (int index);
- Prende e restituisce l'elemento dal layout dall'indice o restituisce 0 se non ce n'è.
- Qt :: Orientations expandingDirections () const;
- Restituisce le direzioni espandendo i layout.
- bool hasHeightForWidth () const;
- Indica se il layout gestisce l'altezza per il calcolo della larghezza.
- QSize minimumSize () const;
- Restituisce la dimensione minima del layout.
- void setGeometry (const QRect & amp; rect);
- Imposta la geometria del layout e gli elementi al suo interno. Qui devi mantenere le proporzioni e centrare.
- QSize sizeHint () const;
- Restituisce la dimensione preferita per il layout.
Ulteriori letture
Chiamare resize ()
dall'interno di resizeEvent ()
non ha mai funzionato bene per me - nella migliore delle ipotesi causerà sfarfallio poiché la finestra viene ridimensionata due volte (come hai fatto ), nel peggiore dei casi un ciclo infinito.
Penso che " corretto " il modo per mantenere le proporzioni fisse consiste nel creare un layout personalizzato. Dovrai sovrascrivere solo due metodi, QLayoutItem :: hasHeightForWidth ()
e QLayoutItem :: heightForWidth ()
.
Nel mio caso la sostituzione di heightForWidth () non funziona. E, per qualcuno, potrebbe essere utile ottenere un esempio funzionante dell'uso dell'evento resize.
Alla prima sottoclasse qObject per creare il filtro. Ulteriori informazioni sui filtri degli eventi.
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
};
Quindi la funzione eventFilter. Il suo codice deve essere definito al di fuori della definizione FilterObject per evitare avvisi. Grazie a questa risposta.
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;
};
Quindi, nel codice principale, creare FilterObject e impostarlo come listener EventFilter sull'oggetto target. Grazie a questa risposta.
FilterObject *filter = new FilterObject();
QWidget *targetWidget = new QWidget();//let it be target object
filter->target=targetWidget;
targetWidget->installEventFilter(filter);
Ora il filtro riceverà tutti gli eventi targetWidget e imposterà l'altezza corretta all'evento di ridimensionamento.