Вопрос

Как можно сохранить соотношение сторон виджетов в Qt и как насчет центрирования виджета?

Это было полезно?

Решение

Вам не нужно реализовывать свой собственный менеджер макета. Вы можете сделать с наследованием QWidget и переопределением

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

чтобы оставаться на месте. Однако heightForWidth() не работает на окнах верхнего уровня на X11, поскольку, очевидно, протокол X11 этого не поддерживает. Что касается центрирования, вы можете передать Qt::AlignCenter в качестве третьего параметра QBoxLayout::addWidget() или пятого параметра QGridLayout::addWidget().

Примечание: . По крайней мере, в более новых версиях Qt QWidget больше не имеет heightForWidth или widthForHeight (поэтому их нельзя переопределить), и поэтому setWidthForHeight(true) или setHeightForWidth(true) действуют только для потомков QGraphicsLayout .

Другие советы

Правильный ответ — создать собственный менеджер макетов.Это возможно путем подкласса QLayout.

Методы, реализуемые при создании подкласса QLayout

void addItem (элемент QLayoutItem*);
Добавляет элемент в макет.
интервал счетчика () константа;
Возвращает количество элементов.
QLayoutItem* itemAt(int index) const;
Возвращает ссылку на элемент по индексу или 0, если ее нет.
QLayoutItem* takeAt(int index);
Берет и возвращает элемент из макета из индекса или возвращает 0, если его нет.
Qt::Ориентации ExpandingDirections() const;
Возвращает направления расширения макетов.
bool hasHeightForWidth() const;
Сообщает, обрабатывает ли макет высоту для расчета ширины.
QSize minSize() const;
Возвращает минимальный размер макета.
void setGeometry (const QRect& rect);
Задает геометрию макета и элементов внутри него.Здесь вам придется сохранить соотношение сторон и выполнить центрирование.
QSize sizeHint() const;
Возвращает предпочтительный размер макета.

дальнейшее чтение

Вызов 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 и устанавливать правильную высоту при изменении размера.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top