在调整大小期间保持子类QWidget的宽高比

Spi*_*ine 12 c++ qt qwidget

我正在创建一个新的小部件,通过继承QWidget类.我希望能够为这个小部件设置一个比例(高度和宽度),它将始终保持不变.

为此,我总是使用Qt5文档,Google和Stackoverflow进行搜索.显然,我找到了答案:特别是这一个.但是,不幸的是,甚至没有一个是完全有效的:

  • sizeIncrement即使窗口小部件是窗口,设置也完全没有
  • 我试图重载resizeEvent,但我真的不知道怎么做...
  • 如果我按照这个答案,有两件事:

    1. 如果小部件是顶级窗口,则根本不保持比例,我可以根据需要调整大小.
    2. 如果我将此小部件放置在布局中,如果我只增加窗口的宽度和高度,则保持该比率.但是一旦我将宽度或高度增加到很多,小部件就会变平.相反,我希望布局自动调整其大小以保持小部件的比例.

那么,我怎样才能保持子类QWidget的宽高比?

Ant*_*ony 11

创建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);
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!该解决方案是对我有用的唯一解决方案,它继承了QOpenGLWidget。我在构造函数中添加了`layout-> setContentsMargins(0,0,0,0);`以删除边距。 (2认同)

Mat*_*phy 5

我在 Python/PySide2 中重写了 Anthony 的代码:

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)
Run Code Online (Sandbox Code Playgroud)