Сохранения пропорций суб класс от QWidget в размер
Я создаю новый виджет, подклассом класса QWidget. Я хотел бы иметь возможность установить соотношение (для его высоты и ширины) для этого виджета, которое всегда будет поддерживаться.
для этого я всегда искал, используя документацию Qt5, Google и Stackoverflow. Очевидно, я нашел ответы: в частности, этот. Но, к сожалению, даже один не является полностью эффективным:
- задание
sizeIncrement
ничего не делает, даже если виджет-окно - Я пытался перегрузить resizeEvent, но я действительно не знаю, как это сделать...
-
Если я буду следовать ответ, две вещи:
- если виджет является окном верхнего уровня, соотношение не поддерживается вообще, я могу изменить его размер, как я хочу.
- если я помещаю этот виджет в макет, если я просто увеличиваю ширину и высоту окна, соотношение сохраняется. Но как только я увеличу ширину или высота к много, виджет сплющен. Вместо этого я хотел бы, чтобы макет автоматически настраивал свой размер, чтобы сохранить соотношение виджета.
Итак, как мне удалось сохранить соотношение сторон подкласса QWidget?
2 ответов
создать родительский виджет (например, AspectRatioWidget
) в котором разместить виджет. Для родительского виджета подкласс QWidget и дать ему QBoxLayout. Поместите виджет в центр, а QSpacerItems с обеих сторон. Затем в Родительском виджете QWidget::resizeEvent
отрегулируйте направление и растяжки по мере необходимости. Я привел пример ниже. Чтобы использовать, просто создайте экземпляр AspectRatioWidget
и передайте конструктору указатель на ваш виджет и нужное соотношение сторон.
// header
class AspectRatioWidget : public QWidget
{
public:
AspectRatioWidget(QWidget *widget, float width, float height, QWidget *parent = 0);
void resizeEvent(QResizeEvent *event);
private:
QBoxLayout *layout;
float arWidth; // aspect ratio width
float arHeight; // aspect ratio height
};
// cpp
AspectRatioWidget::AspectRatioWidget(QWidget *widget, float width, float height, QWidget *parent) :
QWidget(parent), arWidth(width), arHeight(height)
{
layout = new QBoxLayout(QBoxLayout::LeftToRight, this);
// add spacer, then your widget, then spacer
layout->addItem(new QSpacerItem(0, 0));
layout->addWidget(widget);
layout->addItem(new QSpacerItem(0, 0));
}
void AspectRatioWidget::resizeEvent(QResizeEvent *event)
{
float thisAspectRatio = (float)event->size().width() / event->size().height();
int widgetStretch, outerStretch;
if (thisAspectRatio > (arWidth/arHeight)) // too wide
{
layout->setDirection(QBoxLayout::LeftToRight);
widgetStretch = height() * (arWidth/arHeight); // i.e., my width
outerStretch = (width() - widgetStretch) / 2 + 0.5;
}
else // too tall
{
layout->setDirection(QBoxLayout::TopToBottom);
widgetStretch = width() * (arHeight/arWidth); // i.e., my height
outerStretch = (height() - widgetStretch) / 2 + 0.5;
}
layout->setStretch(0, outerStretch);
layout->setStretch(1, widgetStretch);
layout->setStretch(2, outerStretch);
}
я переписал код Энтони в Python / PySide2:
from PySide2.QtWidgets import QBoxLayout, QSpacerItem, QWidget
class AspectRatioWidget(QWidget):
def __init__(self, widget, parent):
super().__init__(parent)
self.aspect_ratio = widget.size().width() / widget.size().height()
self.setLayout(QBoxLayout(QBoxLayout.LeftToRight, self))
# add spacer, then widget, then spacer
self.layout().addItem(QSpacerItem(0, 0))
self.layout().addWidget(widget)
self.layout().addItem(QSpacerItem(0, 0))
def resizeEvent(self, e):
w = e.size().width()
h = e.size().height()
if w / h > self.aspect_ratio: # too wide
self.layout().setDirection(QBoxLayout.LeftToRight)
widget_stretch = h * self.aspect_ratio
outer_stretch = (w - widget_stretch) / 2 + 0.5
else: # too tall
self.layout().setDirection(QBoxLayout.TopToBottom)
widget_stretch = w / self.aspect_ratio
outer_stretch = (h - widget_stretch) / 2 + 0.5
self.layout().setStretch(0, outer_stretch)
self.layout().setStretch(1, widget_stretch)
self.layout().setStretch(2, outer_stretch)