C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > Qt复杂抽屉效果

Qt实现小功能之复杂抽屉效果详解

作者:中国好公民st

在Qt自带的控件中,也存在抽屉控件:QToolBar。但是,该控件有个缺点:一次只能展开一个抽屉信息,无法实现多个展开。所以本文将自定义实现复杂抽屉效果,需要的可以参考一下

在Qt自带的控件中,也存在抽屉控件:QToolBar。但是,该控件有个缺点:一次只能展开一个抽屉信息,无法实现多个展开。为此,实现了如下效果的程序:

下面对这种实现效果进行讲解~

功能讲解

开发环境:VS2017 + Qt5.14.2 64位

实现的核心技术:

1:QScrollArea的应用。

2:垂直布局的应用。

根据展示效果可以发现:一个标题下面对应了一个显示窗口,标题的下拉按钮控制了粉色窗口的显示和隐藏。

接下来,由内向外进行实现。

自定义标题widget

类名:QSingleTitleWidget

代表了每一个单独的标题窗口。包含了两个控件:QLabel、QCheckBox,分别展示标题名称以及控制是否展示对应的内容窗口

标题名称控件的创建

QString qsLabelStyle = "QLabel{color:#333333; font-family:Microsoft YaHei UI; font-size:18px;} QLabel{background-color: transparent}";
m_labTitle = new QLabel(this);
m_labTitle->setGeometry(10, 0, 200, 60);
m_labTitle->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
m_labTitle->setStyleSheet(qsLabelStyle);
m_labTitle->show();

QCheckBox控件的创建

QString qsCheckStyle = "QCheckBox{color:#333333;font-family:Microsoft YaHei UI;font-size:14px;}"
"QCheckBox::indicator::checked{image:url(:/QMultipleToolBarWidget/image/jd_zk_s.png)}"
"QCheckBox::indicator::unchecked{image:url(:/QMultipleToolBarWidget/image/jd_sq_n.png)}"; 
m_check = new QCheckBox(this);
m_check->setGeometry(500, 5, 50, 60);
m_check->setStyleSheet(qsCheckStyle);
connect(m_check, &QCheckBox::clicked, this, &QSingleTitleWidget::OnCheckShowState);
m_check->show();
m_check->setChecked(false);

在标题类(QSingleTitleWidget)中需要实现QCheckBox的响应消息,通知外界该标题类对应的内容类是显示还是隐藏状态。

"setChecked(false)":默认窗口一创建就让粉色窗口处于隐藏状态。

对于QCheckBox的消息的实现,如下:

void QSingleTitleWidget::OnCheckShowState(bool checked /*= false*/)
{
	emit Msg_SendShowState(m_nNum, checked);
}

其中,m_nNum是当前标题窗口的编号,在通知外界的同时也需要告诉外界,是哪个窗口发生了变化!

补充一点:在QSingleTitleWidget类中也可以不实现QCheckBox响应消息,直接使用QWidget::mousePressEvent消息做处理,这里不再详细说明!

自定义内容Widget

类名:QSingleContentWidget

代表了每一个单独的内容窗口。仅有一个控件:QLabel,只是用于提示窗口的高度。

其实在实际开发中,可以展示更丰富的内容,这里只是展示了不同高度。

创建显示高度描述控件

QString qsLabelStyle = "QLabel{color:#333333; font-family:Microsoft YaHei UI; font-size:18px;} QLabel{background-color: transparent}";
m_labContent = new QLabel(this);
m_labContent->setStyleSheet(qsLabelStyle);
m_labContent->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
m_labContent->show();

设置具体的高度值

void QSingleContentWidget::SetContent(int nHeight)
{
	QString qsContent = QStringLiteral("当前窗口高度是:") + QString::number(nHeight);
	m_labContent->setGeometry(10, 10, 540, nHeight-20);
	m_labContent->setText(qsContent);
}

以上1、2两部分内容分别描述了标题widget、内容widget,下面需要创建一个承载这些内容的widget载体,将在QScrollArea中使用。

QScrollArea中widget实现

类名:QScrollAreaWidget

该类是一个承载多个标题、内容的widget,也是直接由外部调用的类。

假设:传入一个std::vector<int>的容器,容器的多少大小代表的是标题的个数,int值是随机生成的高度值。

但是,到了真正业务应用中时,这里的int没准就是一个结构体,或者是一个数据指针,无论是什么,处理方式都是一样的。

对外开放接口:

void QScrollAreaWidget::SetScrollAreaData(std::vector<int> vetWidget)
{
    //数据处理
}

根据vetWidget的大小创建出对应的数据组(一个标题、一个内容)

直接上全部代码~

int nTop = 0;
for (int i = 0; i < vetWidget.size(); i++)
{
	//创建:标题
	QSingleTitleWidget *widgetTitle = new QSingleTitleWidget(this);
	widgetTitle->setFixedSize(560, 60);
	widgetTitle->SetTitleContent(i);
	bool bShowState = i == 0 ? true : false;
	widgetTitle->SetShowState(bShowState);
	widgetTitle->show();
	connect(widgetTitle, &QSingleTitleWidget::Msg_SendShowState, this, &QScrollAreaWidget::MsgReceivedTitleControlShowState);
	m_vetTitleWidget.push_back(widgetTitle);
	m_layout.addWidget(widgetTitle);
	nTop += 60 + 5;

	//创建:内容
	QSingleContentWidget *widgetContent = new QSingleContentWidget(this);
	widgetContent->setFixedSize(QSize(560, vetWidget[i]));
	widgetContent->SetContent(vetWidget[i]);
	if (bShowState == true)
	{
		widgetContent->show();
		nTop += vetWidget[i] + 5;
	}
	else
	{
		widgetContent->hide();
	}
	m_mapContentWidget.insert(std::make_pair(i, widgetContent));
	m_layout.addWidget(widgetContent);

}
m_layout.addStretch(0);
m_layout.setSpacing(5);
this->setLayout(&m_layout);

m_nTotalHeight = nTop;

this->setFixedSize(QSize(560, nTop));

代码讲解:

1:创建标题类:QSingleTitleWidget、创建内容类:QSingleContentWidget。

这两个类是一对一对应的。其中,这里有个小逻辑处理,当编号是0时(也就是第一组数据时)默认处于显示状态。

采用了三目运算符,方便简单:bool bShowState = i == 0 ? true : false;

并且,在创建QSingleContentWidget类时,根据是否显示状态来控件该类是否显示。

2:消息处理

之前在QSingleTitleWidget类中发送了一个QCheckBox的消息,在这里就运用到该消息了。

Msg_SendShowState参数值=true时,代表展示QSingleContentWidget类内容;反之,隐藏QSingleContentWidget类的内容。

3:垂直布局应用

每创建一个新的widget,需要将widget添加到布局中:m_layout.addWidget(widgetTitle);

最后,需要在当前类中绑定布局:this->setLayout(&m_layout);

4:nTop值的意义

每创建一个类都需要对nTop进行追加,主要是为了扩大QScrollArea子窗口widget的大小,其实在使用布局后不使用也没有关系,但是为了能够让我们控制widget的高度,最好主动进行设置。

QScrollArea子窗口的提升

从Qt Designer中拖出来的QScrollArea控件,默认会自带一个widget子控件,上述3下的功能就是对子控件的重写,那么该如何绑定呢?

选中提升后,出现下面页面

红框里面就是需要提升的类文件以及类名。

注意:设置了提升的类名称后,默认头文件会自动添加,但是该头文件是不区分大小写!这里一定要改成与实际的头文件名称保持一致!

刚开始做的时候未区分大小写,结果找了半天才找到原因,这也跟Qt版本有关系,最好与我们提升的类一一对应!

到此这篇关于Qt实现小功能之复杂抽屉效果详解的文章就介绍到这了,更多相关Qt复杂抽屉效果内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文