【问题标题】:QTreeWidgetItem hierarchy to SQLQTreeWidgetItem 层次结构到 SQL
【发布时间】:2019-04-19 16:33:56
【问题描述】:

我想将 QTreeWidget 的内容存储到 MySQL 数据库中。

表描述的SQL是:

CREATE TABLE category (
id          int not null,
parentId    int,
name        varchar(1024), );

其中 parentId 是引用同一表中的 id 的外键。 (意味着执行一个自我加入)

使用 QtCreator,以下代码可以正常工作:

int FactsBuilder::findChildren( QTreeWidgetItem *node, int top )
{

    for( int i = 0; i < node->childCount(); ++i )
    {

       QTreeWidgetItem *item = node->child(i);
       qDebug() << "Child: " << top++ << " - "  << item->text(0);
       if(item->childCount() > 0 ) {

           this->findChildren(item, top++ );
       }
    }

    return top;
}

void FactsBuilder::updateCatSQL()
{

    int count = 1;
    for( int i = 0; i < ui->treeWidget->topLevelItemCount(); ++i )
    {

       QTreeWidgetItem *item = ui->treeWidget->topLevelItem( i );
       qDebug() << "Item Number: " << count++ <<  " - " << item->text(0);


       if(item->childCount() > 0 ) {
            count = this->findChildren( item, count);
       }
    }
}

一些示例输出:

Top:  1  -  "foo"
Top:  2  -  "bar"
Child:  3  -  "beer"
Child:  4  -  "ice"
Top:  5  -  "bla"
Top:  6  -  "baz"

顶部项没有父项,因此在这种情况下,MySQL 数据库中的 parentId 列将包含 NULL。

在这种情况下,在其文本属性中存储“beer”和“ice”的 QTreeWidgetItems 将导致在数据库的 parentId 列中存储“2”。因为它们是在 QTreeWidgetItem 下组织的,“bar”存储在其文本属性中。

第一种情况

除非带有“ice”的 QTreeWidgetItems 将被组织在带有“beer”的 QTreeWidgetItem 的文本属性中。

在这种情况下,我希望数据库的 parentId 列中有“2”和“3”。

第二种情况

【问题讨论】:

    标签: c++ qt qt5 qtreeview


    【解决方案1】:

    首先,如果你的表设计得更好,解决方案会被简化,更好的做法是让 id 字段为自增:

    CREATE TABLE IF NOT EXISTS category  (
        id          int NOT NULL AUTO_INCREMENT PRIMARY KEY,
        parentId    int,
        name        varchar(1024)
    )
    

    然后我创建了一个从QTreeWidget 接收invisibleRootItem() 的方法,并由数据库中的信息保存。

    #include <QtWidgets>
    #include <QtSql>
    
    static bool createConnection(){
        QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
        db.setHostName("hostname");
        db.setDatabaseName("databasename");
        db.setUserName("username");
        db.setPassword("password");
        if (!db.open()) {
            qDebug()<<"Cannot open database\n"
                      "Unable to establish a database connection.\n"
                      "This example needs SQLite support. Please read "
                      "the Qt SQL driver documentation for information how "
                      "to build it.\n\n"
                      "Click Cancel to exit.";
            return false;
        }
        QSqlQuery query;
        query.exec("DROP TABLE IF EXISTS category;");
        if(!query.exec(R"(CREATE TABLE IF NOT EXISTS category  (
                       id          int NOT NULL AUTO_INCREMENT PRIMARY KEY,
                       parentId    int,
                       name        varchar(1024)
                       ))"))
            qDebug()<<query.lastError().text();
        return true;
    }
    static void fill_model(QTreeWidget &tree){
        QTreeWidgetItem *foo_item = new QTreeWidgetItem({"foo"});
        QTreeWidgetItem *bar_item = new QTreeWidgetItem({"bar"});
        QTreeWidgetItem *bla_item = new QTreeWidgetItem({"bla"});
        QTreeWidgetItem *baz_item = new QTreeWidgetItem({"baz"});
        for(QTreeWidgetItem *item : {foo_item, bar_item, bla_item, baz_item})
            tree.addTopLevelItem(item);
        QTreeWidgetItem *beer_item = new QTreeWidgetItem({"beer"});
        QTreeWidgetItem *beer_child_item = new QTreeWidgetItem({"beer_child"});
        QTreeWidgetItem *ice_item = new QTreeWidgetItem({"ice"});
        for(QTreeWidgetItem *item : {beer_item, ice_item})
            bar_item->addChild(item);
        beer_item->addChild(beer_child_item);
        beer_child_item->addChild(new QTreeWidgetItem({"beer_child_child"}));
    }
    static void save_to_db(const QString & tablename, QTreeWidgetItem* parent, int parent_id=0){
        for(int i=0; i< parent->childCount(); ++i){
            QTreeWidgetItem *child_item = parent->child(i);
            QSqlQuery query(QString("INSERT INTO %1 (parentId, name) VALUES (?, ?)").arg(tablename));
            if(parent_id != 0)
                query.bindValue(0, parent_id);
            query.bindValue(1, child_item->text(0));
            if(!query.exec())
                qDebug()<< query.lastError().text();
            save_to_db(tablename, child_item, query.lastInsertId().toInt());
        }
    }
    int main(int argc, char *argv[]){
        QApplication a(argc, argv);
        if(!createConnection())
           return -1;
        QWidget w;
        QTreeWidget tree_widget;
        fill_model(tree_widget);
        save_to_db("category", tree_widget.invisibleRootItem());
        tree_widget.expandAll();
        QTableView table_view;
        QSqlTableModel model;
        model.setTable("category");
        model.select();
        table_view.setModel(&model);
        QHBoxLayout *hlay = new QHBoxLayout(&w);
        hlay->addWidget(&tree_widget);
        hlay->addWidget(&table_view);
        w.resize(640, 480);
        w.show();
        return a.exec();
    }
    

    【讨论】:

    • 你在哪里声明category.parentId作为category.id的外键?
    • 在表描述sql中添加FOREIGN KEY (parentId) REFERENCES category(id)
    • 或添加 ALTER TABLE 类别 ADD CONSTRAINT fk_category FOREIGN KEY (parentId) REFERENCES category(id); 任何你喜欢的地方。 (在您执行此操作之前,该表必须存在。)
    • @DagmarHofman 我的想法是为您提供如何保存 MySql 的逻辑,我的解决方案有效吗?
    • @DagmarHofman 如果我的回答对您有帮助,请不要忘记将其标记为正确,如果您不知道该怎么做,请查看tour
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-10
    • 2011-08-27
    • 2020-11-30
    • 2017-02-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多