Qt的QTreeView控件实现节点的增删改功能并保存入库

1.首先需要使用Qt创建一个Qt GUI应用.

Qt的QTreeView控件实现节点的增删改功能并保存入库_第1张图片

2.基类选择QWidget.

Qt的QTreeView控件实现节点的增删改功能并保存入库_第2张图片

3.自动生成好的工程目录如下,而kqdicwidget.ui文件和相应的.cpp和.h文件是我后来添加的按钮弹出窗口文件.

Qt的QTreeView控件实现节点的增删改功能并保存入库_第3张图片

4.设计好UI界面,对象名如下.

Qt的QTreeView控件实现节点的增删改功能并保存入库_第4张图片

4.如下就是dicwidget.cpp文件的代码.

   dicwidget.h文件如下.

#ifndef DICWIDGET_H
#define DICWIDGET_H

#include 
#include 
#include 

namespace Ui {
class DicWidget;
}

class DicWidget : public QWidget
{
    Q_OBJECT

public:
    explicit DicWidget(QWidget *parent = 0);
    ~DicWidget();

private:
    Ui::DicWidget *ui;

public slots:
    void curIndex();                        //combobox的信号与槽函数

private slots:
    void on_AddBtn_clicked();

    void on_UpdataBtn_clicked();

    void on_DelBtn_clicked();

    void on_ExitBtn_clicked();

    void on_SaveBtn_clicked();

private:
    void InitCombo();                       //初始化Combobox
    void ConnectDataBase();                 //连接数据库
    void LoadTree();                        //刷新树列表
    void reftree(QStandardItem*);           //递归遍历树
    void reftreechild(QStandardItem*,int&); //递归遍历子项

private:
    QStandardItemModel *model;              //标准项目模型

public:
    QStandardItem *currentItem;

public:
    QMap NameTypeMap;        //QMap方便数据的映射
    QString addName;
    QStringList listname;
    QList listslid;
    QList listdlid;
    QStringList header;
    QString dicname;
    QString name;
    QString type;
    int refslid;            //定义全局变量
    int refdlid;
};

#endif // DICWIDGET_H

   dicwidget.cpp文件如下.

#include "dicwidget.h"
#include "ui_dicwidget.h"
#include 

#include 
#include 
#include 
#include "kqdatedicwidget.h"

#include 
#include 
#include 
#include 

#pragma execution_character_set("utf-8")

DicWidget::DicWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::DicWidget)
{
    ui->setupUi(this);
    this->setFixedSize(540,300);
    //初始化combobox控件
    InitCombo();
    connect(ui->comboBox,SIGNAL(currentIndexChanged(QString)),this,SLOT(curIndex()));
    //设置窗口的属性
    this->setWindowFlags(Qt::WindowCloseButtonHint|Qt::MSWindowsFixedSizeDialogHint);
    ui->treeView->setEditTriggers(QAbstractItemView::NoEditTriggers);    //设置TreeView为不可编辑
}

DicWidget::~DicWidget()
{
    delete ui;
}

void DicWidget::InitCombo()    //初始化combobox
{
    ConnectDataBase();         //连接本地数据库方法

    QSqlQuery query;
    query.exec("select * from ATT_DIC_TREE where SJID = 0 order by type");

    while(query.next())
    {
        QString map_name = query.value(0).toString();    //获取数据库字段值
        QString map_type = query.value(1).toString();
        NameTypeMap[map_name] = map_type;                //使用QMap映射值
        ui->comboBox->addItem(map_name);                 //设置值到combobox上
    }
}

void DicWidget::curIndex()    //combobox的点击后执行的槽方法
{
    ConnectDataBase();

    QSqlQuery query;
    QString rSql = QString("SELECT * FROM ATT_DIC_TREE where TYPE = '%1' and sjid = 0").arg(NameTypeMap[ui->comboBox->currentText()]);    //使用映射获取数据库的type
    query.exec(rSql);

    header.clear();        //QStringList的header的变量

    while(query.next())
    {
        QString r_name = query.value(4).toString();
        dicname = query.value(4).toString();
        header << r_name;    //获取的值存入header中
    }

    model = new QStandardItemModel(ui->treeView);
    //model->setHorizontalHeaderLabels(QStringList()<setHorizontalHeaderLabels(header);    //设置TreeView的头标题

    listname.clear();        //清空List数据
    listslid.clear();
    listdlid.clear();

    LoadTree();
}

void DicWidget::LoadTree()        //加载树控件
{
    QSqlQuery query;

    QString dtype = NameTypeMap[ui->comboBox->currentText()];    //映射出type
//    int i = ui->comboBox->currentIndex();
//    QString dtype = QString::number(i+1,10);
    QString sql = QString("SELECT * FROM ATT_DIC_TREE where TYPE = '%1' order by SJID,DLID;").arg(dtype);
    query.exec(sql);
    //如下开始从QMap中的数据加载到树控件上
    while(query.next())
    {
        QMap mMapItems;

        while(query.next())
        {
            int dlid = query.value(2).toInt();
            int sjid = query.value(3).toInt();
            QString name = query.value(4).toString();
            if(sjid==0 || mMapItems.constFind(sjid)==mMapItems.constEnd())
            {
                QStandardItem *itemProject2 = new QStandardItem(name);
                itemProject2->setData(name);
                model->appendRow(itemProject2);

                mMapItems[dlid]=itemProject2;
            }
            else if(mMapItems.constFind(sjid)!=mMapItems.constEnd())
            {
                QStandardItem* pPar=mMapItems[sjid];
                QStandardItem* item0 = new QStandardItem(name);
                item0->setData(name);
                pPar->appendRow(item0);

                mMapItems[dlid]=item0;
            }
            if(name.isEmpty())
                break;
        }
        break;
    }

    QString NameTypeSql = QString("SELECT * FROM ATT_DIC_TREE where type = '%1' and sjid = 0").arg(dtype);
        query.exec(NameTypeSql);
    while(query.next())
        name = query.value(0).toString();

    ui->treeView->setModel(model);
}

void DicWidget::ConnectDataBase()        //与本地mdb数据库的连接
{
    QString sDbNm ="C:/Users/Administrator/Desktop/SysDic.mdb";    //路径可修改
    QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
    QString dsn = QString("DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};FIL={MS Access};DBQ=%1;").arg(sDbNm);
    db.setDatabaseName(dsn);
    db.setUserName("");
    db.setPassword("");

    bool ok = db.open();
    if(!ok)
    {
        QMessageBox messagebox;
        messagebox.setText("Database error");
        messagebox.exec();
        db.close();
    }
}

void DicWidget::on_AddBtn_clicked()        //添加按钮的方法
{
    QStandardItemModel *model1 = static_cast(ui->treeView->model());
    QModelIndex currentindex = ui->treeView->currentIndex();
    if(currentindex.row()==-1)            //如果未选中树节点的一项则return
        return;
    currentItem = model1->itemFromIndex(currentindex);

    kqDateDicWidget dlg;    //点击按钮后弹出一个窗口进行数据的添加
    dlg.setTitle("add");    //次窗口的ui是kqdatadicwidget.ui相应的.cpp和.h文件见项目目录
    dlg.setModal(true);
    dlg.exec();

    QString additem = dlg.GetValues();    //获取弹出窗口输入的值
    if(!additem.isEmpty())
    {
        QStandardItem *itemChild = new QStandardItem(additem);
        currentItem->appendRow(itemChild);

        ui->treeView->setExpanded(currentindex,true);    //每添加一项则展开当前子项
    }

//    ConnectDataBase();
//    QSqlQuery query;
//    QString sql = QString("SELECT * FROM ATT_DIC_TREE where DICNAME = '%1' order by SJID,DLID;").arg(currentItem->text());
//    query.exec(sql);

//    while(query.next())
//    {
//        addDlid = query.value(2).toInt();
//        addName = query.value(0).toString();
//    }


//    int i = ui->comboBox->currentIndex();
//    QString dtype = QString::number(i+1,10);
//    QString maxDlidSql = QString("SELECT max(DLID) FROM ATT_DIC_TREE where type = '%1'").arg(dtype);
//    query.exec(maxDlidSql);

//    while(query.next())
//        maxDlid = query.value(0).toInt();
}

void DicWidget::on_UpdataBtn_clicked()        //修改按钮的方法
{
    QStandardItemModel *model1 = static_cast(ui->treeView->model());
    QModelIndex currentindex = ui->treeView->currentIndex();
    if(currentindex.row()==-1)
        return;
    currentItem = model1->itemFromIndex(currentindex);

    kqDateDicWidget dlg;
    dlg.setTitle("update");
    dlg.setModal(true);
    dlg.exec();

    QString additem = dlg.GetValues();
    if(!additem.isEmpty())
    {
        //QStandardItem *itemChild = new QStandardItem(additem);
        currentItem->setText(additem);        //实现修改树节点的文本
    }
}

void DicWidget::on_DelBtn_clicked()        //删除树节点的方法
{
    QStandardItemModel *model1 = static_cast(ui->treeView->model());
    QModelIndex currentindex = ui->treeView->currentIndex();
    if(currentindex.row()==-1)        //如果没有选中树节点则提示需要选中节点
    {
        int war = QMessageBox::warning(NULL,"warning","Please select a deletion item !",QMessageBox::Yes|QMessageBox::No,QMessageBox::Yes);
        if(war == QMessageBox::Yes || war == QMessageBox::No)
            return;
    }

    int rb = QMessageBox::warning(NULL,"warning","Are you sure to delete !",QMessageBox::Yes|QMessageBox::No,QMessageBox::Yes);
    if(rb == QMessageBox::Yes)
    {
        currentItem = model1->itemFromIndex(currentindex);
        if(!currentItem->parent())
        {
            model1->removeRow(currentindex.row());
            //currentItem->removeRows(0,currentItem->rowCount());
            //delete currentItem->takeRow(currentindex.row());
            return;
        }

        QStandardItem *parent = currentItem->parent();
        parent->removeRow(currentindex.row());        //删除树节点
        //delete parent->takeChild(currentindex.row());
    }
}

void DicWidget::reftree(QStandardItem* item)        //递归遍历树的方法开始
{
    if(item==nullptr)
        return;

    QString itemname = item->text();        //获取树的一层节点的数据
    listname.append(itemname);
    listslid.append(refslid);
    listdlid.append(refdlid);

    reftreechild(item,refdlid);        //开始遍历树节点的子项节点
}

void DicWidget::reftreechild(QStandardItem* model,int& dlid)        //递归子项的方法
{
    int nSJID=dlid;
    for(int i=0;irowCount();i++)
    {
        QStandardItem* childitem2 =  model->child(i);
        dlid++;
        QString childtext = childitem2->text();    //设置下一个节点
        listname.append(childtext);
        listslid.append(nSJID);
        listdlid.append(dlid);

        reftreechild(childitem2,dlid);        //递归
    }
}

void DicWidget::on_SaveBtn_clicked()        //保存按钮的方法
{
    refslid = 1;    //通过数据库的规则从根节点的下一个节点开始遍历(设置初始值)
    refdlid = 2;    //自身id为2的开始设置
    for(int i =0;irowCount();i++)
    {
        QStandardItem* childItem = model->item(i,0);
        reftree(childItem);    //调用遍历树的方法
        refdlid++;             //除去根节点的下一级节点的id自加
    }

    ConnectDataBase();
    QSqlQuery query;

//    int i = ui->comboBox->currentIndex();
//    QString dtype = QString::number(i+1,10);

    QString dtype = NameTypeMap[ui->comboBox->currentText()];
    //先删除当前选中的combobox的数据
    QString delSql = QString("delete from ATT_DIC_TREE where type = '%1'").arg(dtype);
    query.exec(delSql);
    //开始保存入库,将根节点的数据保存如数据库中
    QString root_str = dicname;
    QString firstSql = QString("insert into ATT_DIC_TREE (NAME,TYPE,DLID,SJID,DICNAME,DICCODE) values ('%1','%2',%3,%4,'%5','%6')").arg(name).arg(dtype).arg(1).arg(0).arg(root_str).arg(123);
    query.exec(firstSql);
    //开始将所有节点(除去根节点)保存入数据库中
    for(int n=0;nclose();
}

5.如下就是点击按钮后弹出一个窗口,用来修改数据的ui文件和.cpp文件还有.h文件.

   kqdatedicwidget.ui文件的设计如下.

Qt的QTreeView控件实现节点的增删改功能并保存入库_第5张图片

   kqdatedicwidget.h文件代码如下.

#ifndef KQDATEDICWIDGET_H
#define KQDATEDICWIDGET_H

#include 

namespace Ui {
class kqDateDicWidget;
}

class kqDateDicWidget : public QDialog
{
    Q_OBJECT

public:
    explicit kqDateDicWidget(QWidget *parent = 0);
    ~kqDateDicWidget();

private slots:
    void on_pushButton_2_clicked();

    void on_okBtn_clicked();

private:
    Ui::kqDateDicWidget *ui;

public:
    QString addname;

public:
    QString GetValues();
    void setTitle(QString);

signals:
    void dlgReturn(QString);
};

#endif // KQDATEDICWIDGET_H

   kqdatedicwidget.cpp文件代码如下.

#include "kqdatedicwidget.h"
#include "ui_kqdatedicwidget.h"
#include 

kqDateDicWidget::kqDateDicWidget(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::kqDateDicWidget)
{
    this->setMinimumSize(200,120);
    this->setMaximumSize(200,120);
    //设置窗口的属性
    this->setWindowFlags(Qt::WindowCloseButtonHint|Qt::MSWindowsFixedSizeDialogHint);

    ui->setupUi(this);
}

kqDateDicWidget::~kqDateDicWidget()
{
    delete ui;
}

void kqDateDicWidget::on_pushButton_2_clicked()        //取消按钮的方法
{
    this->close();
}

void kqDateDicWidget::on_okBtn_clicked()        //确定按钮的方法
{
    addname = ui->lineEdit->text();             //获取文本框的值
    if(addname.isEmpty())
    {
        QMessageBox::information(NULL,"Tip","Please enter text !",QMessageBox::Yes|QMessageBox::No,QMessageBox::Yes);
        return;
    }

    this->close();
}

QString kqDateDicWidget::GetValues()
{
    return addname;        //返回文本框的值
}

void kqDateDicWidget::setTitle(QString type)    //根据点击的按钮的不同来设置窗口的标题
{
    if(type == "add")
        this->setWindowTitle("Add Fileds");
    else if(type == "update")
        this->setWindowTitle("Update Fileds");
    else if(type == "delete")
        this->setWindowTitle("Delete Files");
}

6.下面就是main.cpp的文件了main.cpp文件没有什么修改的.

#include "dicwidget.h"
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    DicWidget w;
    w.setWindowTitle("QtTreeView的设置");
    w.show();

    return a.exec();
}

7.实现的效果图片.

  未修改treeview节点的原数据图如下.

Qt的QTreeView控件实现节点的增删改功能并保存入库_第6张图片

     然后我在棒球节点下添加一个 "陈棒球" 节点,我再修改自行车节点为 "大雄的自行车",最后删除胖虎节点,最后点击保存.

Qt的QTreeView控件实现节点的增删改功能并保存入库_第7张图片

   下面是修改win10的树控件的风格为win7的风格,让TreeView控件有连接线

#include 

构造函数里面
{
    ui->setupUi(this);
    ......
    ui->treeView->setStyle(QStyleFactory::create("windows"));//让行政区树有连接线
}

   效果如下:

Qt的QTreeView控件实现节点的增删改功能并保存入库_第8张图片

 

 

   需要下载该小工具项目的源码和该项目的mdb数据库的请点击链接: : https://download.csdn.net/download/superman___007/10983400

 或者在百度云链接: https://pan.baidu.com/s/1bxI31qrknLi4Ci-nkR5ycQ 提取码: 98hr 

 

那童年的希望是 一台 时光机  《时光机》

 

你可能感兴趣的:(♪,--,Qt)