【二十四】【QT开发应用】ScorllArea应用3,补全ScorllArea代码以及ListWidget与ScorllArea联动的信号槽和槽函数编写

补全ScorllArea代码逻辑

我们将其他ListItem项目全部设置成和基本设置一样的代码,唯独不一样的就是把题头的label修改成对应的文本,例如基本设置,云盘设置等。
在这里插入图片描述

Widget对应一个类

每一个Widget创建对应的类,头文件和cpp文件,里面的代码和CBaseSetWidget类代码类似。
在这里插入图片描述
唯一不一样的就是把题头的Text文本修改成对应的文本。
在这里插入图片描述

主Widget中定义每个类的指针对应一个widget

在这里插入图片描述

定义存储widget指针的vector

在主widget中定义全局变量vector存储widget指针。
在这里插入图片描述

将各个widget创建并添加到ScorllArea

QWidget* pWidget = new QWidget;
QVBoxLayout* pVLayout = new QVBoxLayout(pWidget);


m_pBaseSetWidget = new CBaseSetWidget;
m_pYunpanSetWidget = new CYunPanSetWidget;
m_pDownloadWidget = new CDownloadWidget;
m_pJieguanWidget = new CJieguanWidget;
m_pRenwuWidget = new CRenwuWidget;
m_pTixingWidget = new CTixingWidget;
m_pXuanfuWidget = new CXuanfuWidget;
m_pGaoJiWidget = new CGaojiWidget;

m_vecWidget.push_back(m_pBaseSetWidget);
m_vecWidget.push_back(m_pYunpanSetWidget);
m_vecWidget.push_back(m_pDownloadWidget);
m_vecWidget.push_back(m_pJieguanWidget);
m_vecWidget.push_back(m_pRenwuWidget);
m_vecWidget.push_back(m_pTixingWidget);
m_vecWidget.push_back(m_pXuanfuWidget);
m_vecWidget.push_back(m_pGaoJiWidget);


pVLayout->addWidget(m_pBaseSetWidget);
pVLayout->addWidget(m_pYunpanSetWidget);
pVLayout->addWidget(m_pDownloadWidget);
pVLayout->addWidget(m_pJieguanWidget);
pVLayout->addWidget(m_pRenwuWidget);
pVLayout->addWidget(m_pTixingWidget);
pVLayout->addWidget(m_pXuanfuWidget);
pVLayout->addWidget(m_pGaoJiWidget);


m_pScrollArea->setWidget(pWidget);

widget的继承应用

QWidget* pWidget = new QWidget;
QVBoxLayout* pVLayout = new QVBoxLayout(pWidget);
首先我们创建一个pwidget,将各个widget整合成这一个pwidget最后只需要将ScorllArea设置成这个整体pwidget即可。

1. QWidget* pWidget = new QWidget;

  • 这是一个普通的 QWidget,它作为容器,用来容纳其他控件。您可以将它看作是一个空的窗口或区域,可以添加其他控件和布局。

2. QVBoxLayout* pVLayout = new QVBoxLayout(pWidget);

  • 这是一个垂直布局管理器 (QVBoxLayout)。
  • pVLayout 是指向 QVBoxLayout 的指针,它将控件垂直堆叠在一起(从上到下)。
  • pWidget 被作为布局的父对象,所有控件都将在 pWidget 内按垂直顺序排列。

此时我们只需要填写pVLayout控件即可,pVLayout控件会自动添加到pWidget

ListWidget与ScorllArea信号联动

	connect(m_pListWidget, &QListWidget::itemClicked, this, &demo14_ScorllArea::slotItemClicked);


	connect(m_pScrollArea->verticalScrollBar(), &QScrollBar::valueChanged,
		this, &demo14_ScorllArea::slotValueChanged);

这段代码使用了 Qt 信号与槽机制,将控件的某些事件(比如 QListWidget 的 item 点击和 QScrollBar 的滚动条值变化)与特定的槽函数(处理程序)关联起来。

1. connect(m_pListWidget, &QListWidget::itemClicked, this, &demo14_ScorllArea::slotItemClicked);

  • m_pListWidget 是指向 QListWidget 的指针。
  • itemClickedQListWidget 的一个信号,表示列表中的某一项被点击时触发。
  • this 是当前对象(通常是一个类的实例,demo14_ScorllArea)。
  • slotItemClicked 是槽函数,当列表中的一项被点击时,它会被调用。该函数通常会处理与点击事件相关的逻辑。

2. connect(m_pScrollArea->verticalScrollBar(), &QScrollBar::valueChanged, this, &demo14_ScorllArea::slotValueChanged);

  • m_pScrollArea->verticalScrollBar() 获取 QScrollArea 中的垂直滚动条。
  • valueChanged 是滚动条的信号,当滚动条的值发生变化时触发。滚动条的值对应于当前滚动的进度。
  • slotValueChanged 是槽函数,当滚动条的值变化时调用,通常用来同步其他控件的状态或者执行滚动相关的操作。

总结:

  1. 当用户点击 QListWidget 中的某个项时,slotItemClicked 函数将会被调用。
  2. QScrollArea 的滚动条滚动时,slotValueChanged 函数将会响应这个变化并处理相关逻辑。

ListWidget与ScorllArea联动的槽函数编写

void demo14_ScorllArea::slotItemClicked(QListWidgetItem* item) {
	signFlag = true;
	QString itemText = item->text();
	QPoint widgetPos;

	int size = m_textList.size();
	for (int i = 0; i < size; i++) {
		if (itemText == m_textList[i]) {
			widgetPos = m_vecWidget[i]->pos();
		}
	}

	m_pScrollArea->verticalScrollBar()->setValue(widgetPos.y());
}

void demo14_ScorllArea::slotValueChanged(int value) {
	if (!signFlag) {
		int itemSize = m_vecWidget.size();
		for (int i = 0; i < itemSize; i++) {
			if (!m_vecWidget[i]->visibleRegion().isEmpty()) {
				m_pListWidget->item(i)->setSelected(true);
				return;
			} else {
				m_pListWidget->item(i)->setSelected(false);
			}
		}
	}

	signFlag = false;
}

这段代码通过实现两个槽函数,完成了 QListWidgetQScrollArea 之间的联动。当用户点击 QListWidget 的项目时,滚动区域会自动滚动到对应的内容。当用户手动滚动时,列表中的项目会自动选中与当前可见内容相关的项目。

ListWidget中itemClicked信号会传递选中的item给槽函数

1. slotItemClicked(QListWidgetItem* item)

这个槽函数在用户点击 QListWidget 中的某个项目时被触发。

  • signFlag = true;:设置标记,用于防止滚动条值变化时引发的多余操作(防止递归触发 slotValueChanged)。
  • itemText = item->text();:获取被点击的 QListWidgetItem 的文本。
  • 遍历 m_textList,找到点击的项目对应的 m_vecWidget 中的控件,并获取该控件的位置(widgetPos)。
  • m_pScrollArea->verticalScrollBar()->setValue(widgetPos.y());:根据找到的控件的位置,将滚动条的值设置为该控件的垂直坐标,进而让 QScrollArea 滚动到该控件的位置。
示例:
void demo14_ScorllArea::slotItemClicked(QListWidgetItem* item) {
    signFlag = true;
    QString itemText = item->text();  // 获取被点击的项目文本
    QPoint widgetPos;

    // 遍历找到与 itemText 匹配的控件
    int size = m_textList.size();
    for (int i = 0; i < size; i++) {
        if (itemText == m_textList[i]) {
            widgetPos = m_vecWidget[i]->pos();  // 获取控件的位置
        }
    }

    // 设置滚动条的值,让 QScrollArea 滚动到控件位置
    m_pScrollArea->verticalScrollBar()->setValue(widgetPos.y());
}
2. slotValueChanged(int value)

这个槽函数在 QScrollArea 的垂直滚动条值发生变化时被触发。

  • 首先检查 signFlag,确保该变化不是由点击事件引发的滚动。
  • 遍历 m_vecWidget,检查哪些控件的可见区域非空(即可见),并选中与之对应的 QListWidgetItem
  • m_pListWidget->item(i)->setSelected(true);:选中对应的列表项。
  • signFlag = false;:重置 signFlag,允许下一次点击或滚动正常触发。
示例:
void demo14_ScorllArea::slotValueChanged(int value) {
    if (!signFlag) {
        int itemSize = m_vecWidget.size();
        for (int i = 0; i < itemSize; i++) {
            if (!m_vecWidget[i]->visibleRegion().isEmpty()) {  // 检查控件是否可见
                m_pListWidget->item(i)->setSelected(true);  // 选中对应的列表项
                return;
            } else {
                m_pListWidget->item(i)->setSelected(false);  // 取消其他项目的选中状态
            }
        }
    }

    signFlag = false;
}

关键点:

  1. signFlag 的作用

    • 通过 signFlag 来避免由于点击列表项导致的滚动和由于滚动引发的列表项选中产生的递归触发。
    • 当点击列表项时,signFlag 被设为 true,这确保 slotValueChanged 不会在滚动条值变化时立即处理。
  2. m_vecWidgetm_textList

    • m_vecWidget 是与 QListWidget 的项目相对应的 QWidget 对象的容器(通常是控件的指针数组)。
    • m_textList 是存储 QListWidget 项目文本的列表,确保能根据点击的项目找到对应的 QWidget

功能总结:

  • 当用户点击 QListWidget 的某个项目时,slotItemClicked 会让 QScrollArea 自动滚动到与该项目相关的内容。
  • 当用户手动滚动 QScrollArea 时,slotValueChanged 会自动更新 QListWidget 的选中项,保持列表与内容同步。

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。
同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。
谢谢您的支持,期待与您在下一篇文章中再次相遇!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

妖精七七_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值