qt-C++笔记之在两个标签页中按行读取两个不同的文件并且滚动条自适应滚动范围高度
code review!
文章目录
- qt-C++笔记之在两个标签页中按行读取两个不同的文件并且滚动条自适应滚动范围高度
- 1.运行
- 2.文件结构
- 3.main.cc
- 4.main.pro
- 5.a.txt
- 6.b.txt
- 7.上述代码中QVBoxLayout,QScrollArea,QTabWidget,QWidget,QLayoutItem之间的关系
- 8.QLayoutItem *item = layout->itemAt(i);
- 9.QLayout和QLayoutItem的关系
1.运行
2.文件结构
3.main.cc
代码
#include <QApplication>
#include <QDebug>
#include <QFile>
#include <QPushButton>
#include <QScrollArea>
#include <QTabWidget>
#include <QTextStream>
#include <QVBoxLayout>
#include <QWidget>
#include <QScrollBar>
#include <QLabel>
// 计算内容部件的总高度
int calculateContentHeight(QVBoxLayout *layout) {
int height = 0;
for (int i = 0; i < layout->count(); ++i) {
QLayoutItem *item = layout->itemAt(i);
if (item && item->widget()) {
height += item->widget()->height();
height += layout->spacing();
}
}
return height;
}
// 调整QScrollArea的滚动范围高度
void adjustScrollRangeHeight(QScrollArea *scrollArea, QWidget *contentWidget) {
QVBoxLayout *layout = qobject_cast<QVBoxLayout *>(contentWidget->layout());
if (layout) {
int contentHeight = calculateContentHeight(layout);
scrollArea->verticalScrollBar()->setRange(0, contentHeight);
}
}
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建主窗口
QWidget window;
window.setWindowTitle("文件读取示例");
// 创建 QTabWidget
QTabWidget tabWidget(&window);
// 创建第一个标签页
QWidget tab1Widget;
QVBoxLayout *tab1Layout = new QVBoxLayout(&tab1Widget);
QScrollArea scrollArea1;
scrollArea1.setFixedHeight(300); // 设置高度为300像素
QWidget scrollAreaContent1;
QVBoxLayout *scrollAreaLayout1 = new QVBoxLayout(&scrollAreaContent1);
tab1Layout->addWidget(&scrollArea1);
tabWidget.addTab(&tab1Widget, "文本文件1");
// 创建第二个标签页
QWidget tab2Widget;
QVBoxLayout *tab2Layout = new QVBoxLayout(&tab2Widget);
QScrollArea scrollArea2;
scrollArea2.setFixedHeight(300); // 设置高度为300像素
QWidget scrollAreaContent2;
QVBoxLayout *scrollAreaLayout2 = new QVBoxLayout(&scrollAreaContent2);
tab2Layout->addWidget(&scrollArea2);
tabWidget.addTab(&tab2Widget, "文本文件2");
// 连接按钮1的点击事件
QPushButton button1("读取文件1");
QObject::connect(&button1, &QPushButton::clicked, [&]() {
// 清空第一个标签页的内容
QLayoutItem *item;
while ((item = scrollAreaLayout1->takeAt(0)) != nullptr) {
delete item->widget();
delete item;
}
// 读取文件1内容并添加到第一个标签页的 QScrollArea
QFile file1("/home/user/qt_cpp_test/test_templete/a.txt");
if (file1.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file1);
while (!in.atEnd()) {
QString line = in.readLine();
QLabel *label = new QLabel(line);
scrollAreaLayout1->addWidget(label);
}
file1.close();
// 调整滚动范围高度
adjustScrollRangeHeight(&scrollArea1, &scrollAreaContent1);
} else {
qDebug() << "Error opening file 1: " << file1.errorString();
}
// 将滚动区域的内容部件设置为滚动区域的子部件
scrollAreaContent1.setLayout(scrollAreaLayout1);
scrollArea1.setWidget(&scrollAreaContent1);
});
// 连接按钮2的点击事件
QPushButton button2("读取文件2");
QObject::connect(&button2, &QPushButton::clicked, [&]() {
// 清空第二个标签页的内容
QLayoutItem *item;
while ((item = scrollAreaLayout2->takeAt(0)) != nullptr) {
delete item->widget();
delete item;
}
// 读取文件2内容并添加到第二个标签页的 QScrollArea
QFile file2("/home/user/qt_cpp_test/test_templete/b.txt");
if (file2.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file2);
while (!in.atEnd()) {
QString line = in.readLine();
QLabel *label = new QLabel(line);
scrollAreaLayout2->addWidget(label);
}
file2.close();
// 调整滚动范围高度
adjustScrollRangeHeight(&scrollArea2, &scrollAreaContent2);
} else {
qDebug() << "Error opening file 2: " << file2.errorString();
}
// 将滚动区域的内容部件设置为滚动区域的子部件
scrollAreaContent2.setLayout(scrollAreaLayout2);
scrollArea2.setWidget(&scrollAreaContent2);
});
// 将按钮添加到主窗口
QVBoxLayout *mainLayout = new QVBoxLayout(&window);
mainLayout->addWidget(&button1);
mainLayout->addWidget(&button2);
mainLayout->addWidget(&tabWidget);
window.show();
return app.exec();
}
4.main.pro
代码
QT += widgets
TARGET = FileContentReader
TEMPLATE = app
SOURCES += main.cpp
HEADERS +=
FORMS +=
DISTFILES += \
5.a.txt
代码
555555555555555555555555555
22222222222222222222
99999999999999999999
22
adrewerr
222222222222222222223
ewofjedoiw
3ferfhjnerwifje
fejlieflewiehu3
sjdfuewhjrouiehur
fuewlaifijdqwipjd
djiwpadjwiaodj
juewidjheupiwrfjdeo
wjuiqdijewioedh
jewuipqdjfql
6.b.txt
代码
jgfyfeyjfgegg
ekeo2jwojriw
efjkfehf99999
7.上述代码中QVBoxLayout,QScrollArea,QTabWidget,QWidget,QLayoutItem之间的关系
在上述代码中,QVBoxLayout
、QScrollArea
、QTabWidget
、QWidget
和QLayoutItem
之间的关系如下:
QVBoxLayout
是用于垂直布局的布局管理器,它可用于将多个小部件垂直排列在一起。QScrollArea
是一个可滚动的视图区域,它提供了一种方式来显示包含大量内容的小部件。它可以包含一个单独的小部件作为其内容,该部件可以是任何派生自QWidget
的类。QTabWidget
是一个选项卡式容器,它可以包含多个标签页。每个标签页显示为一个选项卡,点击选项卡可以切换显示不同的内容。QWidget
是Qt中所有用户界面元素的基类,它是一个可视化的窗口或部件。它可以作为QScrollArea
的内容部件,用于显示滚动区域中的内容。QLayoutItem
是布局管理器中的项,它代表一个小部件或布局。它用于在布局中管理小部件的位置和大小。
在给定的代码中,QVBoxLayout
用于管理每个标签页的布局,QScrollArea
作为每个标签页的滚动区域,QWidget
是QScrollArea
的内容部件,QLayoutItem
用于管理滚动区域中的小部件的位置和大小。
整体关系如下:
QTabWidget
├── QWidget (tab1Widget)
│ └── QVBoxLayout (tab1Layout)
│ └── QScrollArea (scrollArea1)
│ └── QWidget (scrollAreaContent1)
│ └── QVBoxLayout (scrollAreaLayout1)
│ └── QLabel (label1)
│ └── QLabel (label2)
│ ...
├── QWidget (tab2Widget)
│ └── QVBoxLayout (tab2Layout)
│ └── QScrollArea (scrollArea2)
│ └── QWidget (scrollAreaContent2)
│ └── QVBoxLayout (scrollAreaLayout2)
│ └── QLabel (label1)
│ └── QLabel (label2)
│ ...
...
每个标签页中包含一个QWidget
,每个QWidget
中使用QVBoxLayout
进行布局管理,其中包含一个QScrollArea
作为滚动区域,滚动区域的内容部件是一个QWidget
,该部件中使用QVBoxLayout
进行内容布局,其中包含多个QLabel
作为文本标签。
这段程序使用了Qt框架来创建一个带有两个标签页的QTabWidget,每个标签页中都有一个QScrollArea,用于显示文本文件内容。下面是程序中各个部件之间的关系:
- QTabWidget是主窗口的子部件。
- 每个标签页(QWidget)是QTabWidget的子部件。
- 每个标签页内部有一个垂直布局(QVBoxLayout),用于放置QScrollArea。
- 每个QScrollArea设置了固定的高度,并且有一个内容部件(QWidget)作为其子部件。
- 每个内容部件内部有一个垂直布局(QVBoxLayout),用于放置QLabel。
- 每个QLabel用于显示文本文件的一行内容。
此外,还定义了一些辅助函数用于计算内容部件的总高度和调整滚动范围的高度。按钮1和按钮2的点击事件会清空相应标签页的内容,然后读取文本文件的内容并添加到对应的QScrollArea中,最后调整滚动范围的高度。
总结起来,程序的结构如下:
- 主窗口(QWidget)
- QTabWidget
- 标签页1(QWidget)
- 垂直布局1(QVBoxLayout)
- QScrollArea1
- 内容部件1(QWidget)
- 垂直布局1(QVBoxLayout)
- QLabel1
- QLabel2
…
- 垂直布局1(QVBoxLayout)
- 内容部件1(QWidget)
- QScrollArea1
- 垂直布局1(QVBoxLayout)
- 标签页2(QWidget)
- 垂直布局2(QVBoxLayout)
- QScrollArea2
- 内容部件2(QWidget)
- 垂直布局2(QVBoxLayout)
- QLabel1
- QLabel2
…
- 垂直布局2(QVBoxLayout)
- 内容部件2(QWidget)
- QScrollArea2
- 垂直布局2(QVBoxLayout)
- 标签页1(QWidget)
- 按钮1(QPushButton)
- 按钮2(QPushButton)
- QTabWidget
8.QLayoutItem *item = layout->itemAt(i);
这行代码的语法如下:
-
QLayoutItem *item
:这是一个变量声明语句,用于定义一个指向QLayoutItem
对象的指针变量,名称为item
。QLayoutItem
是Qt框架中用于布局管理的基类,它可以表示布局中的各种元素,例如部件、空白间隔等。 -
layout->itemAt(i)
:这是一个函数调用表达式,用于获取给定索引位置i
处的布局项。layout
是一个指向QVBoxLayout
对象的指针,表示要获取布局项的垂直布局。itemAt(i)
是QVBoxLayout
类的成员函数,返回一个指向QLayoutItem
对象的指针,该对象表示布局中的一个元素。
整体来看,这行代码的作用是在给定的垂直布局layout
中获取索引为i
的布局项,并将其保存到名为item
的指针变量中。通过这个指针变量,可以进一步访问和操作该布局项的相关属性和方法。
需要注意的是,此处的代码假设了layout
指针和i
的合法性,即layout
指针不为空且有效,i
是一个有效的索引值。否则,在使用item
指针之前应该进行有效性检查,以确保代码的健壮性。
QLayoutItem
是QVBoxLayout
的基类,而QVBoxLayout
是QLayoutItem
的派生类。这意味着QVBoxLayout
继承了QLayoutItem
的属性和方法,并且可以被当作QLayoutItem
的一种特殊类型来使用。
在Qt中,布局管理器(例如QVBoxLayout
)用于管理部件的位置和大小。布局管理器负责决定部件如何在容器中进行布局,并提供一些方法来访问和操作布局中的元素。
QVBoxLayout
类中的itemAt(i)
方法是一个成员函数,用于获取指定索引位置i
处的布局项。该方法是从QLayout
类继承而来的,QVBoxLayout
是QLayout
的派生类。返回的指针类型是QLayoutItem*
,表示一个布局项,它可以表示布局中的各种元素,如部件、空白间隔等。
通过itemAt(i)
方法,可以在垂直布局中按索引获取布局项,并进行进一步的操作,例如获取布局项的部件并进行处理。
所以,itemAt(i)
是QVBoxLayout
类的成员函数,返回一个指向QLayoutItem
对象的指针,该对象表示布局中的一个元素。
9.QLayout和QLayoutItem的关系
在Qt中,QLayout
和QLayoutItem
是两个相关的类,用于布局管理器。
-
QLayout
是一个抽象基类,用于定义布局管理器的接口。它提供了一些方法和属性,用于管理和控制布局中的部件和其他元素的位置和大小。QLayout
类本身不能直接使用,而是通过其派生类来实现特定类型的布局管理器,例如QVBoxLayout
、QHBoxLayout
等。 -
QLayoutItem
是QLayout
的子类,表示布局中的一个元素。它可以表示各种类型的元素,包括部件、空白间距、布局等。QLayoutItem
提供了一些方法和属性,用于访问和操作布局元素的信息,例如大小、位置等。
简而言之,QLayout
是布局管理器的接口,定义了布局管理器的基本行为和功能,而QLayoutItem
是布局中单个元素的表示,用于描述和操作布局中的每个部件或其他元素。
通常情况下,使用QLayout
的派生类(例如QVBoxLayout
、QHBoxLayout
)来创建和管理布局,这些派生类继承了QLayout
的接口,并提供了具体的布局算法和方法。而在布局中的每个元素都被表示为QLayoutItem
的实例。