Как поддерживать соотношение сторон виджетов в Qt?
Как можно поддерживать соотношение сторон виджетов в Qt и как насчет центрирования виджета?
4 ответов
вам не нужно реализовывать свой собственный менеджер макетов. Вы можете сделать с наследованием QWidget
и повторно
int QWidget::heightForWidth( int w ) { return w; }
для проживания площади. Однако,heightForWidth()
не работает на окнах верхнего уровня на X11, так как, по-видимому, протокол X11 не поддерживает это. Что касается центрирования, вы можете пройти Qt::AlignCenter
в качестве третьего параметра QBoxLayout::addWidget()
или пятый параметр QGridLayout::addWidget()
.
Примечание: в более новых версиях Qt, по крайней мере, QWidget не имеет heightForWidth
или widthForHeight
больше (поэтому они не могут быть overriden), и поэтому setWidthForHeight(true)
или setHeightForWidth(true)
имеют эффект только для потомков QGraphicsLayout.
правильный ответ-создать пользовательский менеджер макетов. Это возможно путем подкласса объектом qlayout.
методы для реализации при подклассе QLayout
void addItem (QLayoutItem* item); Добавляет элемент в макет. int count () const; Возвращает количество элементов. QLayoutItem* функции itemat(индекс инт) константный; Возвращает ссылку на элемент по индексу или 0, если нет. QLayoutItem * takeAt (индекс int); Берет и возвращает элемент из макета из индекса или возвращает 0, если нет. Qt:: Orientations expandingDirections () const; Возвращает направления расширения макетов. bool hasHeightForWidth () const; Указывает, обрабатывает ли макет высоту для расчета ширины. qsize minimumSize () const; Возвращает минимальный размер макетов. void setGeometry (const QRect& rect); Задает геометрию макета и элементов внутри него. Здесь вы должны поддерживать соотношение сторон и делать центрирование. sizeHint QSize() константный; Возвращает предпочтительный размер макета.более дальнеишее чтение
вызов resize()
внутри resizeEvent()
никогда не работал хорошо для меня-в лучшем случае это вызовет мерцание, поскольку окно изменяется дважды (как у вас), в худшем случае бесконечный цикл.
Я думаю, что "правильный" способ поддерживать фиксированное соотношение сторон-создать пользовательский макет. Вам придется переопределить только два метода, QLayoutItem::hasHeightForWidth()
и QLayoutItem::heightForWidth()
.
в моем случае переопределение heightForWidth () не работает. И для кого-то может быть полезно получить рабочий пример использования события resize.
сначала подкласс qObject для создания фильтра. подробнее о фильтрах.
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
};
затем функция eventFilter. Этот код должен быть определен вне определения FilterObject, чтобы предотвратить предупреждение. благодаря этому ответа.
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;
};
а затем в главном коде создайте FilterObject и установите его как прослушиватель EventFilter для целевого объекта. благодаря этому ответа.
FilterObject *filter = new FilterObject();
QWidget *targetWidget = new QWidget();//let it be target object
filter->target=targetWidget;
targetWidget->installEventFilter(filter);
Теперь фильтр получит все события targetWidget и установит правильную высоту при изменении размера события.