首页 文章

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

提问于
浏览
7

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

为此,我've always searched, using the Qt5 documentation, Google, and Stackoverflow. Obviously, I'找到了答案:特别是this one . 但是,不幸的是,甚至没有一个是完全有效的:

  • 即使窗口小部件是窗口,设置 sizeIncrement 也完全没有

  • 我试图重载resizeEvent,但我真的不知道怎么做...

  • 如果我遵循this answer,有两件事:

  • 如果小部件是顶级窗口,则根本不保持比例,我可以根据需要调整大小 .

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

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

2 回答

  • 9

    创建用于放置窗口小部件的父窗口小部件(例如, 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);
    }
    
  • 0

    我用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)
    

相关问题