Как поддерживать соотношение сторон виджетов в 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 и установит правильную высоту при изменении размера события.