您现在的位置是:首页 >技术杂谈 >Qt/GUI/布局/实现窗口折叠效果/且在操作时父窗口尺寸跟随变动网站首页技术杂谈
Qt/GUI/布局/实现窗口折叠效果/且在操作时父窗口尺寸跟随变动
概述
本文旨在,实现如下所示的显示或隐藏 ‘附加选项’ 的效果,以折的不常用信息和操作项,减少普通用户负担,提升用户体验。在某些软件中此类窗口折叠效果,常用 “…按钮” 来触发。另一种折叠效果是,类似于QQ好友列表那样的,主要是为更有效的利用有限展示空间。
前阵子整理过《Qt/GUI /布局/在父窗中展示多个子窗》,其中在父窗口大小保持不变的情况下,我们可以使用Qt自动布局功能+hide/show操作来实现多个平行窗口的切换效果。因此本以为很容易就能实现这种折叠效果,但事与愿违,碰了点小钉子…
无法resize到小尺寸
如下代码,想着使用Qt布局配合hide/show操作就能完成折叠效果。但是却发现,在折叠操作时,resize回小尺寸却没有生效。
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
ui->setupUi(this);
ui->textEdit->hide();
ui->label_step->setText("1"); //标记操作步骤
//生效 /否则即使执行了hide操作,父窗在显示尺寸上也包含了textEdit大小
this->resize(this->width(), ui->frame->height() + 2);
}
void Widget::on_pushButton_moreInfo_clicked()
{
if (ui->textEdit->isHidden())
{
ui->textEdit->show();
ui->label_step->setText("2");
}
else
{
ui->textEdit->hide();
ui->label_step->setText("3");
//如下操作并没有起到预期效果
this->resize(this->width(), ui->frame->height() + 2);
}
}
QtDesigner 绘制 | 实际运行效果 |
---|---|
在上述示例中,我们点击"更多"按钮,(步骤2)撑大父窗口后,再对父窗口执行hide+resize操作(步骤3)却没能缩小父窗口的尺寸。与《Qt/GUI /布局/在父窗中展示多个子窗》中遇到的问题,本质是一样的。这是为什么呢?
[virtual protected] void QWidget::resizeEvent(QResizeEvent *event)
This event handler can be reimplemented in a subclass to receive widget resize events //which are passed in the event parameter. When resizeEvent() is called, the widget //already has its new geometry. The old size is accessible through QResizeEvent::oldSize().
void Widget::resizeEvent(QResizeEvent *event) {
qDebug() << event->oldSize() << event->size() << this->minimumSize();
}
//初始化过程触发
//QSize(-1, -1) QSize(407, 105) QSize(213, 105)
//展开操作触发
//QSize(407, 105) QSize(407, 311) QSize(213, 311)
//折叠操作时resize操作并没有触发resizeEvent事件
可以发现,minimumSize的尺寸在Qt的布局作用下发生了变化。当在步骤3中执行折叠操作时,由于要resize的尺寸小于minimumSize尺寸,因而操作无法生效。其解决方案,在 QWidget::minimumSize 成员属性中有说明:
minimumSize : QSize
This property holds the widget’s minimum size
The widget cannot be resized to a smaller size than the minimum widget size. The widget’s size is forced to the minimum size if the current size is smaller.
The minimum size set by this function will override the minimum size defined by QLayout. In order to unset the minimum size, use a value of QSize(0, 0).
By default, this property contains a size with zero width and height.
可行方案
经过上述分析,相应的代码修改为:
void Widget::on_pushButton_moreInfo_clicked()
{
if (ui->textEdit->isHidden())
ui->textEdit->show();
else
{
ui->textEdit->hide();
this->setMinimumSize(0, 0);
this->resize(this->width(), ui->frame->height() + 2);
}
}
修正后的代码,执行效果如下:
需要注意的是:在使用自动布局后,QWidget窗口的大小是由布局所管理的。如果您手动调用 resize 函数来设置 QWidget 窗口的大小,则可能会与自动布局相冲突,导致布局无法正确调整 QWidget 窗口的大小。
其他方案
其实Qt的控件库中,QToolBox 号称可以天然的支持这种折叠面板的效果,如QQ好友列表折叠和展开。但是原生的 QToolBox 并不适合实现本文描述的展示效果:它只能实现两个抽屉之间的互斥开关,不支持多个抽屉的同时打开,且当只有一个抽屉时无法将其关上。
关于QToolBox的使用或自定义QToolBox构建,可参见本博客下其他相关文章。此处不再赘述。