Qt | 实现动态创建多个Tab页,页中动态创建多个子部件

1,401 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情

示例运行效果:

1.gif

动态创建Tab按钮和Page页,点击某一个Tab按钮,就会显示对应的Page,Page中动态创建了不同个数的Item。

在MainWindow中创建一个DownloadWidget,DownloadWidget中有一个DownloadForm。DownloadForm中实现动态创建多个Tab页的功能。

上方的每一个Tab按钮为DownloadTabButton,每一个按钮对应一个QWidget页面,QWidget中只有一个QListWidget来管理页面内的所有DownloadItem。

文件目录:

image.png

源码获取: 源码下载地址(CSDN)

具体实现:

实现管理动态创建的Tab按钮

1.设置布局

ui->widget_tab_buttons->layout()->setSizeConstraint(QLayout::SetFixedSize);//设置从顶端开始显示
  • 这一组TabButton是动态创建在一个拥有水平布局的QWidget中的,我们需要将布局设置为从顶端开始显示,这样动态创建的TabButton无论创建多少个,都是从最左端开始排列。
  • 同样的,对于垂直布局,设置这个属性可以保证动态创建的子部件可以在不居中从上向下排列。

2.添加tab按钮

DownloadTabButton *button = new DownloadTabButton(ui->widget_tab);
button->setIndex(iPage);
ui->widget_tab_buttons->layout()->addWidget(button);
connect(button, SIGNAL(sigTabButtonSelected(int)),this, SLOT(slotTabButtonSelect(int)));
  • 在这里要注意为每一个TabButton设置一个索引值,通过索引值我们可以使TabButton和Page对应起来。
  • 添加一个TabButton时,要调用布局的addWidget()函数,将它添加到布局中。

3.通过索引值获取tab按钮的指针

QLayoutItem *child = ui->widget_tab_buttons->layout()->itemAt(index);
if(child != nullptr)
{
    DownloadTabButton *button = static_cast<DownloadTabButton *>(child->widget());
    button->setCancel();
}
  • 调用布局的itemAt()函数,可以通过索引值获取对应的TabButton的指针。
  • 将指针强制转换成DownloadTabButton类,就可以调用类的方法了。

4.删除tab按钮

QLayoutItem *child;
while ((child = ui->widget_tab_buttons->layout()->itemAt(0)) != nullptr)
{
    ui->widget_tab_buttons->layout()->removeItem(child);
    delete child->widget();
    delete child;
    child = nullptr;
}
  • 这里实现的是清空所有的tab按钮。可以类似的实现删除某一个tab按钮。
  • 清空时要注意先调用布局的removeItem()函数,将TabButton移出布局,然后再销毁TabButton。

5.实现滚动条(本例中没有实现,可以自己添加)

ui->scrollArea->verticalScrollBar()->setValue(ui->scrollArea->verticalScrollBar()->minimum());
  • 当创建的TabButton太多,超出Widget的显示区域时,就需要用到滚动框。
  • 将上面的QWidget添加到scrollarea里面就可以了,然后调用上面的代码,实现动态添加完成后,滚动条显示在最左端。

动态创建page页

这里的每一个Page页有一个QWidget类来实现,所有的Page都在一个QstackWidget中,page中又包含一个QListWidget来管理所有的Item。

1.创建page页

QWidget *page = new QWidget(ui->stackedWidget);
QHBoxLayout *layout = new QHBoxLayout(page);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
QListWidget *list = new QListWidget(page);
list->setObjectName("listWidget");
layout->addWidget(list);
ui->stackedWidget->addWidget(page);

2.删除page页

for(int i = ui->stackedWidget->count(); i>=0; i--)
{
    QWidget* widget = ui->stackedWidget->widget(i);
    ui->stackedWidget->removeWidget(widget);
    if(widget != nullptr)
    {
        delete widget;
        widget = nullptr;
    }
}
  • 这里实现的是清空所有的page。
  • 注意这里一定要进行倒序删除,否则会造成崩溃,也可以想上面删除TabButton时一样正序删除,每次都删除第一个。
  • 同样的,要先调用stackedWidget中的removeWidget()函数,将page移出stackedWidget,然后再销毁page。

3.设置某一页显示

ui->stackedWidget->setCurrentIndex(index);

4.获取某一个Page里面的listWidget

QWidget *page = ui->stackedWidget->widget(index);
QListWidget *listWidget = page->findChild<QListWidget *>("listWidget");
  • 先通过index获取到page,再通过findChild()函数,来获取page中名为“listWidget”的子部件。
  • 要使用findChild获取子部件,要先为子部件设置它的objectName。