Qt-QScrollArea&QTabWidget&QStackedWidget&QToolBox等框架

1. QScrollArea

QScrollArea 是一个带滚动条的区域,当内部的内容超过区域本身大小时会显示出滚动条

核心:当 scrollAreaWidgetContents 设置的尺寸不能容纳下内部的部件时,则会显示滚动条

核心方法:

  • setVerticalScrollBarPolicy(Qt::ScrollBarPolicy) :设置垂直滚动策略

    • Qt::ScrollBarAsNeeded : 当内容超过显示区域时则显示滚动条 (推荐)

    • Qt::ScrollBarAlwaysOff : 永远不显示滚动条

    • Qt::ScrollBarAlwaysOn : 一直显示滚动条

  • setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy) :设置水平滚动策略

  • setSizeAdjustPolicy() : 设置滚动条滚动策略

    • QAbstractScrollArea::AdjustIgnored : 不显示滚动条

    • QAbstractScrollArea::AdjustToContents : 根据内容调整是否有滚动条 (推荐)

示例:

cpp 复制代码
ui->scrollArea->setFixedSize(131, 150);
ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
ui->scrollArea->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);

代码方式:

  1. 创建 scrollArea 对象(滚动区域),并设置大小、位置

  2. 创建一个空的 QWidget

  3. 创建一个水平布局或者垂直布局,并加到 QWidget 当中

  4. 向水平布局或者垂直布局中添加所需的部件

  5. 将 QWidget 添加到 ScrollArea 当中

cpp 复制代码
// 1. 实例化滚动区域,并显示到窗口上
QScrollArea *area = new QScrollArea(this);
area->setFixedSize(180, 80);
area->move(250, 20);

// 2. 实例化一个 Widget 和 一个 垂直布局; 让垂直布局关联 Widget
QWidget *w = new QWidget;
QVBoxLayout *v = new QVBoxLayout(w);

// 3. 将所有的按钮添加到 垂直布局当中
for (int i = 1; i <= 10; i++)
{
  QPushButton *btn = new QPushButton(QString("btn_%1").arg(i));
  v->addWidget(btn);
}

// 4. 将Widget 添加到 滚动区域中
area->setWidget(w);

2. QTabWidget

QTabWidget:用来制作选项卡

常用方法:

  • setCurrentIndex(int index) : 设置选中的选项卡

  • setTabPosition(QTabWidget::North, South, West, East) : 设置选项卡的位置

  • setMovable(true/false) :设置选项卡是否可以移动

  • setTabsclosable(true/false) : 设置选项卡是否可以被关闭,true时显示关闭按钮

  • removeTab(index) :关闭 tab 选项卡

  • addTab(QWidget *widget, QString): 添加新的选项卡

信号:

  • currentChanged(int index) : 点击选项卡触发,获取当前选项卡的索引号

  • tabBarClicked(int index) : 点击选项卡触发,获取当前选项卡的索引号

  • tabBarDoubleClicked(int index) : 双击选项卡触发,获取当前选项卡的索引号

  • tabCloseRequested(int index) : 点击关闭按钮时触发,获取当前选项卡的索引号

示例:

cpp 复制代码
// 设置 tabWidget 各种属性
ui->tabWidget->setCurrentIndex(2);
ui->tabWidget->setMovable(true);
ui->tabWidget->setTabPosition(QTabWidget::North);
ui->tabWidget->setTabsClosable(true);


// 添加新选项卡
QWidget *w = new QWidget;
QVBoxLayout *v = new QVBoxLayout(w);
ui->tabWidget->addTab(w, "其他");
v->addWidget(new QLabel("羽毛球还是一如既往的nb"));
v->addWidget(new QLabel("跳水还是一如既往的nb"));
cpp 复制代码
// 移除选中的选项卡
void Widget::on_tabWidget_tabCloseRequested(int index)
{
    ui->tabWidget->removeTab(index);
}

void Widget::on_tabWidget_currentChanged(int index)
{
    qDebug() << index;
}

void Widget::on_tabWidget_tabBarClicked(int index)
{
    qDebug() << "tabBar" << index;
}

void Widget::on_tabWidget_tabBarDoubleClicked(int index)
{
    qDebug() << "tabBar-Double" << index;
}

3. QStackedWidget

QStackedWidget :

  • count() :获取 stacked 长度

  • setCurrentIndex(index) : 设置显示第几页

  • addWidget(*widget) : 向最后添加新页

  • insertWidget(index, *widget) : 在指定位置添加新页

  • currentWidget(*widget) : 获取当前页对象

  • removeWidget(*widget) : 移除指定页

cpp 复制代码
ui->stackedWidget->setCurrentIndex(this->index);

// 添加新页
QWidget *w = new QWidget;
QVBoxLayout *v = new QVBoxLayout(w);
v->addWidget(new QLabel("aaa"));
v->addWidget(new QLabel("bbb"));
v->addWidget(new QLabel("ccc"));
ui->stackedWidget->addWidget(w);

// 上一页
connect(ui->prevBtn, &QPushButton::clicked, [this](){
  this->index = --this->index < 0 ? 0 : this->index;
  ui->stackedWidget->setCurrentIndex(this->index);
});
// 下一页
connect(ui->nextBtn, &QPushButton::clicked, [this](){
  this->index = ++this->index == 3 ? 2 : this->index;
  ui->stackedWidget->setCurrentIndex(this->index);
});

// 移除当前页
connect(ui->removeBtn, &QPushButton::clicked, [=](){
  ui->stackedWidget->removeWidget(ui->stackedWidget->currentWidget());
});

4. QToolBox

addItem() : 向toolbox中添加一个新的分组

用户数据初始化:

cpp 复制代码
/ 单条用户信息结构
struct UserStruct
{
    int id;
    QString username;
    QString userImg;
};
// 用户组数据结构
struct FriendListStruct
{
    QString group;
    QVector<UserStruct> userList;
};
// 用户数据
QVector<FriendListStruct> firendList;


this->firendList = {
  {"艾欧尼亚", {
    {1, "阿狸", ":/images/Ahri"},
    {2, "贾克斯", ":/images/jax"},
    {3, "亚索", ":/images/Yasou"},
    {4, "易大师", ":/images/yi"}
  }},
  {"诺克萨斯", {
    {5, "德莱厄斯", ":/images/Darius"},
    {6, "卡特", ":/images/kate"},
    {7, "瑞文", ":/images/Riven"}
  }},
  {"德玛西亚", {
    {8, "赵信", ":/images/Zhaoxin"},
    {9, "薇恩", ":/images/vn"},
    {10, "娑娜", ":/images/Sona"}
  }}
};
cpp 复制代码
// 创建 QToolBox 
QToolBox *friendBox = new QToolBox(this);
friendBox->setFixedSize(150, 400);
friendBox->move(200, 30);
friendBox->setFrameShape(QFrame::Box);

// 遍历数据, 得到阵营名称
for (auto val : this->firendList)
{
  // 创建一个空的 Widget
  QWidget *w = new QWidget;
  w->setFont(QFont("微软雅黑", 12));
  
  // 遍历用户信息
  for (int i = 0; i < val.userList.size(); i++)
  {
    // 创建单个用户按钮
    UserStruct tmp = val.userList.at(i);
    QToolButton *userBtn = new QToolButton;
    userBtn->resize(150, 50);
    userBtn->setText(tmp.username);
    userBtn->setIcon(QIcon(tmp.userImg));
    userBtn->setIconSize(QSize(20, 20));
    userBtn->move(0, i * 50);
    userBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    userBtn->setParent(w);
  }
	// 将阵营列表添加到 ToolBox 中
  friendBox->addItem(w, val.group);
}

5. QListWidget

  • QListWidget 用来设置列表

    • addItem : 向列表中添加选项,选项必须是 QListWidgetItem 类型

    • insertItem(int row, QListWidgetItem *item) : 在 row 后添加一行

    • setAlternatingRowColors: 设置颜色是否交替

    • setViewMode: 设置列表显示模式

      • QListView::ListMode (列表模式) | QListView::IconMode (图标模式)
  • QListWidgetItem 用来设置列表中的选项

    • setTextAlignment 用来设置文本对齐方式
  • 信号:

    • itemClicked(QListWidgetItem *item) : 单击选中某个选项时触发,参数为当前选中项对象

    • itemDoubleClicked(QListWidgetItem *item) : 双击选中某个选项时触发

    • currentRowChanged(int currentRow) :单击选中某个选项时触发,参数为当前选项的索引号

cpp 复制代码
struct HeroStruct
{
  int id;
  QString heroName;
  QString imgPath;
};

QVector<HeroStruct> heroList;

this->heroList = {
  {1, "艾希", ":/images/ashe"},
  {2, "贾克斯", ":/images/jax"},
  {3, "薇恩", ":/images/vn"},
  {4, "格雷福斯", ":/images/Graves"},
  {5, "卡特", ":/images/kate"}
};
cpp 复制代码
ui->listWidget->setAlternatingRowColors(true);

// 遍历数据
for (int i = 0; i < heroList.size(); i++)
{
  HeroStruct tmp = this->heroList.at(i);
  // 创建数据项
  QListWidgetItem *item = new QListWidgetItem;
  item->setIcon(QIcon(tmp.imgPath));     
  item->setText(tmp.heroName);           
  ui->heroList->addItem(item);
}

// itemClicked 信号在选中某个选项时触发
// 参数:选中项对象
void Widget::on_listWidget_itemClicked(QListWidgetItem *item)
{
    qDebug() << item->text();
}

// currentRowChanged 信号在选中某个选项时触发
void Widget::on_listWidget_currentRowChanged(int currentRow)
{
    qDebug() << "currentRowChanged" << currentRow;
}

// 设置显示方式
void Widget::on_listRadio_clicked()
{
    ui->heroList->setViewMode(QListView::ListMode);
}

void Widget::on_iconRadio_clicked()
{
    ui->heroList->setViewMode(QListView::IconMode);
}

6. QTreeWidget

  • QTreeWidget : 用来设置树形菜单

    • setHeaderLabels : 设置头部

    • addTopLevelItem: 添加顶级节点

  • QTreeWidgetItem : 用来设置树形菜单的项

    • addChild: 添加子节点

示例1: 带表头的树形菜单

cpp 复制代码
// TreeWidget (带表头的树形菜单)
QStringList labels = {"英雄类型", "英雄介绍"};
ui->treeWidget->setHeaderLabels(labels);

// 添加一级菜单(顶级菜单)
QTreeWidgetItem *p = new QTreeWidgetItem({"力量"});
ui->treeWidget->addTopLevelItem(p);
QTreeWidgetItem *m = new QTreeWidgetItem({"敏捷"});
ui->treeWidget->addTopLevelItem(m);
QTreeWidgetItem *z = new QTreeWidgetItem({"智力"});
ui->treeWidget->addTopLevelItem(z);


// 添加二级菜单
QTreeWidgetItem *niutou = new QTreeWidgetItem({"牛头酋长", "长得像牛的力量型英雄"});
p->addChild(niutou);
QTreeWidgetItem *shanqiu = new QTreeWidgetItem({"山丘之王", "会扔锤子的力量型英雄"});
p->addChild(shanqiu);

QTreeWidgetItem *js = new QTreeWidgetItem({"剑圣", "拿把大刀乱砍的敏捷型英雄"});
m->addChild(js);
QTreeWidgetItem *emo = new QTreeWidgetItem({"恶魔猎手", "拿把水果刀乱砍的敏捷型英雄"});
m->addChild(emo);

QTreeWidgetItem *fs = new QTreeWidgetItem({"大法师", "骑着马到处乱跑的法师"});
z->addChild(fs);
QTreeWidgetItem *xz = new QTreeWidgetItem({"先知", "会放电的法师"});
z->addChild(xz);

示例2: 不带表头的树形菜单

cpp 复制代码
// 不带表头的树形菜单
ui->deptWidget->setHeaderHidden(true);

// 创建一级节点
QTreeWidgetItem *s = new QTreeWidgetItem(ui->deptWidget);
s->setText(0, "销售部");
s->setCheckState(0, Qt::Unchecked);
ui->deptWidget->addTopLevelItem(s);

QTreeWidgetItem *t = new QTreeWidgetItem(ui->deptWidget);
t->setText(0, "技术部");
t->setCheckState(0, Qt::Unchecked);
ui->deptWidget->addTopLevelItem(t);

QTreeWidgetItem *h = new QTreeWidgetItem(ui->deptWidget);
h->setText(0, "人事行政部");
h->setCheckState(0, Qt::Unchecked);
ui->deptWidget->addTopLevelItem(h);


// 创建二级节点
QTreeWidgetItem *t1 = new QTreeWidgetItem(t);
t1->setText(0, "研发部");
t1->setCheckState(0, Qt::Checked);
QTreeWidgetItem *t2 = new QTreeWidgetItem(t);
t2->setText(0, "测试部");
t2->setCheckState(0, Qt::Checked);
QTreeWidgetItem *t3 = new QTreeWidgetItem(t);
t3->setText(0, "运维部");
t3->setCheckState(0, Qt::Checked);


QTreeWidgetItem *h1 = new QTreeWidgetItem;
h1->setText(0, "人事部");
h1->setCheckState(0, Qt::Checked);
h->addChild(h1);

QTreeWidgetItem *h2 = new QTreeWidgetItem;
h2->setText(0, "行政部");
h2->setCheckState(0, Qt::Checked);
h->addChild(h2);

// 添加三级菜单
QTreeWidgetItem *h22 = new QTreeWidgetItem;
h22->setText(0, "行政一部");
h22->setCheckState(0, Qt::Checked);
h2->addChild(h22);

// 所有子菜单全部展开
ui->deptWidget->expandAll();

信号: itemClicked() : 点击任何节点时触发

cpp 复制代码
void Widget::on_deptWidget_itemClicked(QTreeWidgetItem *item, int column)
{
    qDebug()  << item->text(0);
}
cpp 复制代码
this->deptList = {
  {1, "销售部", "卖东西的部门", 0, 0},
  {2, "技术部", "搞技术的部门", 0, 0},
  {3, "人事财务部", "搞人的部门", 0, 0},
  {4, "销售一部", "销售一部", 1, 0},
  {5, "销售二部", "销售二部", 1, 0},
  {6, "研发部", "搞项目开发的部门", 2, 0},
  {7, "测试部", "搞项目测试的部门", 2, 0},
  {8, "运维部", "搞项目运维的部门", 2, 0},
  {9, "人事部", "招人的部门", 3, 0},
  {10, "财务部", "发工资的部门", 3, 0}
};


for (auto val : this->deptList)
{
  if (val.pid == 0)
  {
    QTreeWidgetItem *t = new QTreeWidgetItem(ui->deptTree);
    t->setText(0, val.deptName);
    t->setText(1, val.deptDesc);
    t->setCheckState(0, Qt::Unchecked);

    for (auto v : this->deptList)
    {
      if (val.id == v.pid)
      {
        QTreeWidgetItem *sub = new QTreeWidgetItem(t);
        sub->setText(0, v.deptName);
        sub->setText(1, v.deptDesc);
        sub->setCheckState(0, Qt::Unchecked);
        t->addChild(sub);
      }
    }

    ui->deptTree->addTopLevelItem(t);
  }
}

7. QTableWidget

  • QTableWidget : 设置表格

    • setColumnCount(int num) : 设置总列数

    • setRowCount(int num) : 设置行数

    • setHorizontalHeaderLabels(QStringList label): 设置表头

    • setItem(行号,列号,数据项) : 设置单元格数据

  • QTableWidgetItem: 设置单元格内容

cpp 复制代码
heroList = {
  {"张飞", 28, 1},
  {"孙尚香", 18, 0},
  {"貂蝉", 20, 0},
  {"吕布", 35, 1}
};

// 设置表格
// 设置列数
ui->tableWidget->setColumnCount(3);
// 设置表头
ui->tableWidget->setHorizontalHeaderLabels(QStringList() << "姓名" << "年龄" << "性别");
//  {"姓名", "年龄", "性别"}
// 设置行数
ui->tableWidget->setRowCount(5);

// 设置表格数据
ui->tableWidget->setItem(0, 0, new QTableWidgetItem("关羽"));
ui->tableWidget->setItem(0, 1, new QTableWidgetItem("50"));
ui->tableWidget->setItem(0, 2, new QTableWidgetItem("男"));

for(int i = 0; i < heroList.size(); i++)
{
  ui->tableWidget->setItem(i + 1, 0, new QTableWidgetItem(heroList[i].name));
  ui->tableWidget->setItem(i + 1, 1, new QTableWidgetItem(QString::number(heroList[i].age)));
  ui->tableWidget->setItem(i + 1, 2, new QTableWidgetItem(heroList[i].gender == 1 ? "男" : "女"));
}

8. 右键菜单

窗口以及容器都能添加右键菜单

信号:

  • customContextMenuRequested() : 右键菜单信号

方法:

  • setContextMenuPolicy() : 设置右键菜单模式

  • currentRow() : 获取当前选中的行号

  • currentItem() : 获取当前选中的行对象

  • insertItem(int index, QListWidgetItem *item) : 向list指定位置插入新选项

  • removeItemWidget(QListWidgetItem *item) : 移除选中项

  • clear() : 清空列表

示例1: 为 listWidget 添加右键菜单

cpp 复制代码
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
  // 设置右键菜单显示
  ui->heroList->setContextMenuPolicy(Qt::CustomContextMenu);
  
  // 右键菜单
  this->menu = new QMenu;
  this->addAction = this->menu->addAction("插入");
  this->delAction = this->menu->addAction("删除");
  this->clsAction = this->menu->addAction("清空");

  connect(this->addAction, &QAction::triggered, [this](){
    qDebug() << "插入";
    int i = ui->heroList->currentRow();
    ui->heroList->insertItem(i + 1, new QListWidgetItem("new Item"));
  });
  connect(this->delAction, &QAction::triggered, [this](){
    qDebug() << "删除";
    QListWidgetItem *item = ui->heroList->currentItem();
    ui->heroList->removeItemWidget(item);
    delete item;
  });
  connect(this->clsAction, &QAction::triggered, [this](){
    qDebug() << "清空";
    ui->heroList->clear();
  });
}

// 鼠标右键触发菜单
void Widget::on_heroList_customContextMenuRequested(const QPoint &pos)
{
    this->menu->exec(QCursor::pos());
}

示例2: 为窗口增加右键菜单

cpp 复制代码
// 配置窗口的右键策略
this->setContextMenuPolicy(Qt::CustomContextMenu);

// 窗口右键菜单
// 一级菜单
this->winMenu = new QMenu;
this->winMenu->addAction("撤销");
this->winMenu->addSeparator();
this->winMenu->addAction("复制");
this->winMenu->addAction("粘贴");
// 二级菜单
QMenu *l2 = new QMenu("新建");
this->winMenu->addMenu(l2);
l2->addAction("文件夹");
l2->addAction("文本文档");
相关推荐
CodeClimb6 分钟前
【华为OD-E卷-木板 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
CT随17 分钟前
Redis内存碎片详解
java·开发语言
anlog26 分钟前
C#在自定义事件里传递数据
开发语言·c#·自定义事件
奶香臭豆腐39 分钟前
C++ —— 模板类具体化
开发语言·c++·学习
不想当程序猿_1 小时前
【蓝桥杯每日一题】分糖果——DFS
c++·算法·蓝桥杯·深度优先
晚夜微雨问海棠呀1 小时前
长沙景区数据分析项目实现
开发语言·python·信息可视化
graceyun1 小时前
C语言初阶习题【9】数9的个数
c语言·开发语言
cdut_suye1 小时前
Linux工具使用指南:从apt管理、gcc编译到makefile构建与gdb调试
java·linux·运维·服务器·c++·人工智能·python
波音彬要多做1 小时前
41 stack类与queue类
开发语言·数据结构·c++·学习·算法
捕鲸叉1 小时前
C++软件设计模式之外观(Facade)模式
c++·设计模式·外观模式