Skip to content

正点原子QT之项目控制组(基于项) ​

10. 项目控制组(基于项) ​

(1) List Widget:清单控件
(2) TreeWidget:树形控件
(3) Table Widget:表控件

10.1 QListWidget:清单控件 ​

QListWidget 继承 QListView。 QListWidget 类提供了一个基于项的列表小部件。 QListWidget 是一个便捷的类,它提供了一个类似于 QListView 提供的列表视图,但是提供了一个用于添加和删除项目的基于项目的经典接口。 QListWidget 使用内部模型来管理列表中的每个 QListWidgetItem。
QListView 是基于 model 的,需要自己来建模(例如建立 QStringListModel、 QSqlTableModel 等),保存数据,这样就大大降低了数据冗余,提高了程序的效率,但是需要我们对数据建模有一定了解,而 QListWidget 是一个升级版本的 QListView,它已经自己为我们建立了一个数据存储模型(QListWidgetItem),操作方便,直接调用 addItem 即可添加项目(ICON,文字)。

案例:添加“歌曲” ​

例 45_qlistwidget,添加“歌曲”(难度:简单)。本例使用一个 QListWidget 以及一个按钮,当单击按钮时,就会调用系统打开文件窗口,过滤 mp3 后缀的文件(本例使用 touch 指令创建2 个 mp3 后缀的文件,并不是真正的歌曲,在终端输入指令为 touch 0.mp3 1.mp3,

cpp
#include "mainwindow.h"
#include "QFileDialog"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    /* 设置主窗口的显示位置与大小 */
    this->setGeometry(0, 0, 800, 480);

    listWidget = new QListWidget(this);

    /* 设置listWidget的大小 */
    listWidget->setGeometry(0, 0, 480, 480);

    listWidget->addItem("请单击右边的添加项添加内容");

    pushButton = new QPushButton(this);

    /* 设置pushButton的位置与大小 */
    pushButton->setGeometry(540, 200, 200, 100);
    pushButton->setText("添加项");

    /* 信号与槽连接 */
    connect(pushButton, SIGNAL(clicked()),
            this, SLOT(pushButtonClicked()));
}

void MainWindow::pushButtonClicked()
{
    /* 调用系统打开文件窗口,设置窗口标题为“打开文件”,过滤文件名 */
    QString fileName = QFileDialog::getOpenFileName(
                this,tr("添加项"),"",
                tr("Files(*.mp3)")
                );

    /* 判断是否选中打开mp3文件 */
    if (fileName != NULL)
        /* 添加项到列表中 */
        listWidget->addItem(fileName);
}

MainWindow::~MainWindow()
{
}

10.2 QTreeWidget:树形控件 ​

QTreeWidget 继承 QTreeView。 QTreeWidget 类提供了一个使用预定义树模型的树视图。QTreeWidget 类是一个便捷的类,它提供了一个标准的树小部件,具有一个类似于 qt3 中的 QListView 类所使用的基于项目的经典接口。该类基于 Qt 的模型/视图体系结构,并使用默认模型来保存项,每个项都是 QTreeWidgetItem。

案例:群发信息 ​

例 46_qtreewidget,群发信息(难度:一般),本例使用一个 TreeWidget,模拟成一个飞信联系人分组,通过选中组内联系人来“群发”信息。实际并不是真正做一个群发信息的飞信,只是模拟飞信群发信息时选择联系人的场景,通过例子来熟悉 QTreeWidget 的使用。

cpp
#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    /* 设置主窗体大小 */
    this->setGeometry(0, 0, 800, 480);

    /* 实例化 */
    treeWidget = new QTreeWidget(this);

    /* 居中 */
    setCentralWidget(treeWidget);

    /* 清空列表 */
    treeWidget->clear();

    /* 实例化顶层树节点 */
    parentItem = new QTreeWidgetItem(treeWidget);
    parentItem->setText(0, "同事");

    parentItem->setFlags(
                Qt::ItemIsUserCheckable
                | Qt::ItemIsEnabled
                | Qt::ItemIsSelectable
                );
    /* 树节点设置为未选中 */
    parentItem->setCheckState(0, Qt::Unchecked);

    /* 字符串链表 */
    QList <QString> strList;
    strList<<"关羽"<<"刘备"<<"张飞";

    for (int i = 0; i < 3; i++){
        /* 实例化子节点 */
        subItem[i] = new QTreeWidgetItem(parentItem);
        /* 设置子节点的文本,参数0代表第0列 */
        subItem[i]->setText(0, strList[i]);
        /* 设置子节点的属性为用户可选、项开启、项可选 */
        subItem[i]->setFlags(
                    Qt::ItemIsUserCheckable
                    | Qt::ItemIsEnabled
                    | Qt::ItemIsSelectable
                    );
        /* 设置子节点的状态为未选中 */
        subItem[i]->setCheckState(0,Qt::Unchecked);
    }
    /* 信号槽连接 */
    connect(treeWidget,SIGNAL(itemChanged(QTreeWidgetItem* , int)),
            this, SLOT(treeItemChanged(QTreeWidgetItem* , int)));

}

/* 更新树节点函数 */
void MainWindow::updateParentItem(QTreeWidgetItem *item)
{
    /* 获取子节点的父节点(树节点) */
    QTreeWidgetItem* parent = item->parent();
    if(parent == NULL){
        return;
    }
    /* 初始化选中的数目为0,下面根据selectCount来判断树节点的状态 */
    int selectCount = 0;
    /* 获取树节点的子节点总数 */
    int childCount = parent->childCount();
    /* 循环判断子节点的状态 */
    for(int i = 0; i < childCount; i ++){
        QTreeWidgetItem* childItem =parent->child(i);
        /* 判断当前子节点的状是否为选中状态,如果是,则加一 */
        if(childItem->checkState(0) == Qt::Checked) {
            selectCount ++;
        }
    }
    /* 根据selectCount来判断树节点的状态 */
    /* 当选中的子节点小于或等于0时,则为设置树节点为未选中状态 */
    if (selectCount <= 0) {
        /* 设置树节点为未选中状态 */
        parent->setCheckState(0, Qt::Unchecked);
        /* 部分选中时,树节点为半选状态 */
    } else if (selectCount > 0 && selectCount < childCount) {
        /* 设置为半选状态 */
        parent->setCheckState(0, Qt::PartiallyChecked);
        /* 子节点全选时 */
    } else if (selectCount == childCount){
        /* 设置为树节点为选中状态 */
        parent->setCheckState(0, Qt::Checked);
    }
}

void MainWindow::treeItemChanged(QTreeWidgetItem *item, int)
{
    /* 获取子节点总数 */
    int count = item->childCount();

    /* 若顶层树节点选中 */
    if(Qt::Checked == item->checkState(0) ) {
        /* 若选中的项是树节点,count会大于0,否则选中的项是子节点 */
        if (count > 0) {
            for (int i = 0; i < count; i++) {
                /* 子节点全选 */
                item->child(i)->setCheckState(0, Qt::Checked);
            }
        } else {
            /* 子节点处理 */
            updateParentItem(item);
        }
        /* 若顶层树节点取消选中时 */
    } else if (Qt::Unchecked == item->checkState(0)) {
        if (count > 0){
            /* 若选中的项是树节点,count会大于0,否则选中的项是子节点 */
            for (int i = 0; i < count; i++) {
                /* 子节点全不选 */
                item->child(i)->setCheckState(0, Qt::Unchecked);
            }
        } else {
            /* 子节点处理 */
            updateParentItem(item);
        }
    }
}

MainWindow::~MainWindow()
{
}

10.3 QTableWidget:表控件 ​

QTableWidget 继承 QTableView。QTableWidget 类提供了一个带有默认模型的基于项的表视图。表小部件为应用程序提供标准的表显示工具。 QTableWidget 中的项由 QTableWidgetItem 提供。

案例:abelWidget 表格 ​

例 47_qtablewidget, TabelWidget 表格(难度:简单),本例使用一个 TableWidget,绘制一个表格,同时修改项的标题,在表格里可以直接通过双击进行编辑项里的内容,也可以删除项里的内容等。

cpp
#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    /* 设置主窗体的大小与位置 */
    this->setGeometry(0, 0, 800, 480);

    /* 实例化 */
    tableWidget = new QTableWidget(this);
    /* 设置tableWidget表居中 */
    setCentralWidget(tableWidget);
    /* 设置列数 */
    tableWidget->setColumnCount(2);
    /* 设置行数 */
    tableWidget->setRowCount(2);
    /* 使用标签设置水平标题标签 */
    tableWidget->setHorizontalHeaderLabels(
                QStringList()<<"姓名"<<"性别"
                );

    /* 字符串类型链表 */
    QList <QString> strList;
    strList<<"小明"<<"小红"<<"男"<<"女";

    for (int i = 0; i < 4; i++) {
        /* 实例化 */
        tableWidgetItem[i] = new QTableWidgetItem(strList[i]);
        /* 设置文本居中对齐 */
        tableWidgetItem[i]->setTextAlignment(Qt::AlignCenter);
    }
    /* 插入数据,表的index就是一个二维数组数据 */
    tableWidget->setItem(0, 0, tableWidgetItem[0]);
    tableWidget->setItem(1, 0, tableWidgetItem[1]);
    tableWidget->setItem(0, 1, tableWidgetItem[2]);
    tableWidget->setItem(1, 1, tableWidgetItem[3]);

}

MainWindow::~MainWindow()
{
}