QStackedWidget实现自适应紧凑布局

前言

本文提出了一种使QStackedWidget尺寸根据内容自适应调整的解决方法。

问题提出

我们知道,QStackedWidget可以包含多个可切换的子窗口。多个子窗口的高度不一样时,此时将QStackedWidget放在一个垂直布局中,所有子窗口会保持和最高的子窗口相同的高度,从而导致高度原本较少的子窗口出现空白区域,看起来十分不紧凑。如何让QStackedWidget尺寸根据子窗口内容自动调整呢?

原因分析

原因显而易见,QStackedWidget虽然显示当前子窗口,但是当前子窗口的高度会受到其他子窗口的影响。
下面尝试解决此问题。

1. 添加垂直弹簧VerticalSpacer

要想自适应,当然需要加弹簧,加了弹簧后,切换子窗口,所有子窗口还是保持相同的高度,说明还是需要进一步修改。

2. 隐藏非当前子窗口及其的内容(无效方法)

切换到当前子窗口时时,把其他子窗口隐藏。经测试这种方法是无效的。因为从QStackedWidget源码中可以看到,在切换当前子窗口时,其他子窗口已经被隐藏了,我们再隐藏是徒劳的。

3. 添加布局(有效方法)

解决方法是在每个子窗口里加一个垂直布局,将原本的子窗口内容作为一个content_widget放到新加的布局里。在显示当前页面时,隐藏其他页面的content_widget即可。

void showStackedWidgetPage(
        QStackedWidget *stackedWidget, int idx)
{
    stackedWidget->setCurrentIndex(idx);

    // 经测试,隐藏page是不行的,需要隐藏page里面的content_widget
    int page_count = stackedWidget->count();
    for (int i = 0; i < page_count; i++)
    {
        QWidget *page = stackedWidget->widget(i);
        QObjectList objects = page->children();
        for (int j = 0; j < objects.size(); j++)
        {
            QWidget *content_widget = qobject_cast<QWidget *>(objects.at(j));
            if (content_widget)
            {
                content_widget->setVisible(i == idx);
                break; // 这里只是跳出当前页的for循环
            }
        }
    }
}

同理,对于水平不紧凑的问题,就采用添加水平布局来解决。

总结

根据以上内容,猜测可能的原因如下:

因为QStackedWidget里面是使用QStackedLayout实现的,可能是由于QStackedWidget里面的QStackedLayout,和普通的QVBoxLayout、QHBoxLayout在内部元素隐藏时,处理方式不一致导致的。即QStackedLayout中子窗口隐藏,不会留出可被VerticalSpacer压缩的空间,但QVBoxLayout和QHBoxLayout在内部元素隐藏时,会将释放的空间作为可压缩空间被VerticalSapce压缩,从而实现了紧凑的自适应布局。


如果您觉得文章有用,可以关注一下笔者公众号。
QStackedWidget实现自适应紧凑布局_第1张图片

你可能感兴趣的:(Qt开发,Qt)