我的数据存储在数据库的以下列中
|AcName|ActCod|GroupCode|
|parent1| |1| |0|
|child1| |101| |1|
|parent2| |2| |0|
|child2| |201| |2|
我正在使用QTreeView
,QStandardItemModel
和QStandardItem
创建此树形视图,但是我不知道如何将孩子附加到父亲。
我将QStandardItem
项存储到QMap
中,但是如何将子节点附加到父节点,将父节点附加到rootNode
?
代码。
standardModel = new QStandardItemModel(this);
QStandardItem *rootNode = standardModel->invisibleRootItem();
QSqlQuery *itemqry = new QSqlQuery("SELECT GroupCode, AcName, ActCod from adm_ac");
while(itemqry->next()){
int groupcode =itemqry->value(0).toInt();
QString acname = itemqry->value(1).toString();
int ActCod = itemqry->value(2).toInt();
QStandardItem *itemmap = new QStandardItem(acname);
rowItemMap.insert(groupcode, itemmap);
}
}
ui->treeView->setModel(standardModel);
头文件。
QStandardItemModel *standardModel;
QStandardItem *acName1;
QStandardItem *acName2;
QMap<int, QStandardItem*> rowItemMap;
答案 0 :(得分:1)
这里是构建树的另一种方法。该代码还注意子节点在其父节点之前加载的情况。该树将通过两次构建:
编辑:我们使用setData()函数代替setProperty,因为QStardardItem不是QObject派生的。
enum GroupCodeRoleEnum{
GroupCodeRole = Qt::UserRole + 1001,
};
while(itemqry->next())
{
int groupcode =itemqry->value(0).toInt();
QString acname = itemqry->value(1).toString();
int ActCod = itemqry->value(2).toInt();
QStandardItem *itemmap = new QStandardItem(acname);
itemMap->setData(groupcode, GroupCodeRole );
//map of ActCod to itemmap, not GroupCode
rowItemMap.insert(ActCod, itemmap) );
} //End of while -- every node were now loaded.
//build the tree
rowItemMap.insert (0, rootNode ) ;
foreach( QStandardItem * p, rowItemMap.values() ){
int groupCode = p->data( GroupCodeRole ).toInt();
//find the parent from the map
if( p != rootNode ){
QMap<int, QStandardItem* >::iterator it = rowItemMap.find( groupCode );
if( it != rowItemMap.end() ){
QStandardItem* pParent = it.value();
pParent->appendRow( p );
}else {
qDebug() << "Parent not exist for groupCode" << groupCode;
}
}//nomal node
} //foreach
ui->treeView->setModel(standardModel);
测试代码:
QStandardItemModel *standardModel = new QStandardItemModel(this);
QStandardItem *rootNode = standardModel->invisibleRootItem();
//Simulate your while() loop.
addItem(1, 0, "parent 1");
addItem(101, 1, "child 1");
addItem(2, 0, "parent 2");
addItem(201, 2, "child 2");
//childs were loaded before parents
addItem(301, 3, "child 3");
addItem(401, 4, "child 4");
addItem(501, 5, "child 5");
addItem(3, 2, "parent 3");
addItem(4, 2, "parent 4");
addItem(5, 2, "parent 5");
//build the tree
m_map.insert (0, rootNode ) ;
foreach( QStandardItem * p, m_map.values() ){
int groupCode = p->data( GroupCodeRole ).toInt();
//find the parent from the map
if( p != rootNode ){
QMap<int, QStandardItem* >::iterator it = m_map.find( groupCode );
if( it != m_map.end() ){
QStandardItem* pParent = it.value();
pParent->appendRow( p );
}else {
qDebug() << "Parent not exist for groupCode" << groupCode;
}
}//nomal node
} //foreach
ui->treeView->setModel(standardModel);
}
void MainWindow::addItem(int Act, int nGroupCode, QString szName)
{
QStandardItem *itemmap = new QStandardItem( szName );
itemmap->setData(nGroupCode, GroupCodeRole );
//map of ActCod to itemmap, not GroupCode
m_map.insert(Act, itemmap);
}
树已建成:
答案 1 :(得分:0)
一种可能的方法是将ActCod
保存为一个角色,然后使用GroupCode
方法通过match()
进行父级搜索:
#include <QtWidgets>
#include <QtSql>
static bool createConnection(){
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:");
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;
if(!query.exec("CREATE TABLE adm_ac("
"AcName TEXT,"
"ActCod INTEGER,"
"GroupCode INTEGER"
")"))
qDebug()<<query.lastError().text();
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"parent1\", 1, 0)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"child1\", 101, 1)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"parent2\", 2, 0)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"child2\", 201, 2)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"A\", 10000, 101)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"B\", 10001, 201)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"C\", 100000, 10000)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"D\", 100001, 10001)");
return true;
}
enum RelationRoles{
CodeRole = Qt::UserRole + 1000,
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
if(!createConnection())
return -1;
QStandardItemModel model;
QSqlQuery query("SELECT GroupCode, AcName, ActCod from adm_ac");
const QSqlRecord rec = query.record();
while (query.next()) {
QString AcName = query.value(rec.indexOf("AcName")).toString();
int GroupCode = query.value(rec.indexOf("GroupCode")).toInt();
int ActCod = query.value(rec.indexOf("ActCod")).toInt();
QStandardItem *it = new QStandardItem(AcName);
it->setData(ActCod, RelationRoles::CodeRole);
if(GroupCode == 0)
model.invisibleRootItem()->appendRow(it);
else{
QModelIndexList ixs = model.match(model.index(0, 0),
RelationRoles::CodeRole,
GroupCode,
1,
Qt::MatchExactly| Qt::MatchRecursive);
if(ixs.size() > 0){
QStandardItem *parent = model.itemFromIndex(ixs.first());
parent->appendRow(it);
}
}
}
QTreeView w;
w.setModel(&model);
w.expandAll();
w.show();
return a.exec();
}
在您的情况下:
// ...
enum RelationRoles{
CodeRole = Qt::UserRole + 1000,
};
// ...
standardModel = new QStandardItemModel(this);
QSqlQuery query("SELECT GroupCode, AcName, ActCod from adm_ac");
const QSqlRecord rec = query.record();
while (query.next()) {
QString AcName = query.value(rec.indexOf("AcName")).toString();
int GroupCode = query.value(rec.indexOf("GroupCode")).toInt();
int ActCod = query.value(rec.indexOf("ActCod")).toInt();
QStandardItem *it = new QStandardItem(AcName);
it->setData(ActCod, RelationRoles::CodeRole);
if(GroupCode == 0)
standardModel->invisibleRootItem()->appendRow(it);
else{
QModelIndexList ixs = standardModel->match(model.index(0, 0),
RelationRoles::CodeRole,
GroupCode,
1,
Qt::MatchExactly| Qt::MatchRecursive);
if(ixs.size() > 0){
QStandardItem *parent = standardModel->itemFromIndex(ixs.first());
parent->appendRow(it);
}
}
}
ui->treeView->setModel(standardModel);
优点是我们不必创建类似QMap的容器,因此可以避免访问不允许的内存以及元素重复的问题。
UPDATE1:
// ...
QSqlQuery query;
if(!query.exec("CREATE TABLE adm_ac("
"AcName TEXT,"
"ActCod INTEGER,"
"GroupCode INTEGER"
")"))
qDebug()<<query.lastError().text();
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"EXPENSES\", 5, 0)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"SALES\", 4, 0)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"ASSETS\", 1, 0)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"CAPITAL\", 3, 0)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"LIAILITIES\", 2, 0)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"CURRENT ASSETS\", 102, 1)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"FIXED ASSETS\", 101, 1)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"INTANGIBLE FIXED ASSETS\", 10102, 101)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"ACCUM.DEP. FIXED ASSETS\", 10103, 101)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"TANGIBLE FIXED ASSETS\", 10101, 101)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"MACHINERY\", 1010102, 10101)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"COMPUTERS\", 1010103, 10101)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"LAND\", 1010101, 10101)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"OFFICE EQUIPMENTS\", 1010104, 10101)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"MOTOR VEHICLES\", 1010105, 10101)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"COMPUTER SOFTWARE\", 1010203, 10102)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"GOODWILL\", 10102001, 10102)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"PATENTS & TRADE MARKS\", 10102002, 10102)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"ACC.DEP- MOTOR VEHICLES\", 10103004, 10103)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"ACC.DEP- OFFICE EQUIPMENTS\", 10103003, 10103)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"ACC.DEP- MACHINERY\", 10103001, 10103)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"ACC.DEP- COMPUTERS\", 10103002, 10103)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"ACCOUNTS RECEIVABLE\", 10205, 102)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"STOCK\", 1010105, 102)");
query.exec("insert into adm_ac(AcName, ActCod, GroupCode) values(\"DEPOSITS & PREPAYMENTS\", 10212, 102)");
return true;
// ...
UPDATE2:
我忘了提一下,在我的解决方案中,我假定数据是有序的,因为在我的算法中,我认为父级在子级之前,但是在一般情况下它是不正确的,因此必须使用以下命令进行排序:{{ 1}}
ORDER BY ActCod ASC