Solved Use QTreeWidget with non-static data.
-
Hi
dont you need a
ui->treeWidget->addItem(treeItem); ? -
@mrjj Hi,
In 5.9 version QTreeWidget does not have any method addIem()
http://doc.qt.io/qt-5/qtreewidget.html
Maybe I dont say thatui->treeWidget
is a QTreeWidget.
Thanks! -
@ZiketCPP "Before items can be added to the tree widget, the number of columns must be set with setColumnCount()."
See http://doc.qt.io/qt-5/qtreewidget.html
Did you? -
@jsulm
Yes, in the constructor I use this
CONTRUCTOR:ui->setupUi(this); ui->treeWidget->setColumnCount(2); ui->treeWidget->setHeaderLabels(QStringList() << "Name" << "Type");
Function Insert item
//I set this item as header in the tree widget QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui->treeWidget); treeItem->setText(0, "Pepedfsdf"); treeItem->setText(1, "Descdfsdfsdf");
The real question is if I can insert, in any time, elements into QTreeWidget and display it, because it seems that I can't. Maybe I have to call a special function to update the tree or anything, i don't know...
-
QAbstractItemModel* const mdl= ui->treeWidget->model(); const int rowCount =mdl->rowCount(); if(mdl->insertRow(rowCount))){ qDebug("Row Inserted!"); if(mdl->setData(mdl->index(rowCount,0),"Pepedfsdf")) qDebug("Pepedfsdf Written"); if(mdl->setData(mdl->index(rowCount,1),"Descdfsdfsdf")) qDebug("Descdfsdfsdf Written"); }
-
@VRonin
As I suppose, this code only works in the constructor of my class. I will post the code with the changes done.Header.h
#ifndef TREENODESUI_H #define TREENODESUI_H #include <QWidget> #include <QTreeWidgetItem> namespace Ui { class TreeNodesUI; } class TreeNodesUI: public QWidget { Q_OBJECT public: explicit TreeNodesUI(QWidget *parent = 0); ~TreeNodesUI(); void addTreeChild(Node* node_to_add, QString name, QString description); private: Ui::TreeNodesUI *ui; }; #endif // TREENODESUI_H
Source.cpp
#include "treenodesui.h" #include "ui_treenodesui.h" #include <QStringList> #include <QAbstractItemModel> TreeNodesUI::TreeNodesUI(QWidget *parent) : QWidget(parent), ui(new Ui::TreeNodesUI) { ui->setupUi(this); ui->treeWidget->setColumnCount(2); ui->treeWidget->setHeaderLabels(QStringList() << "Name" << "Type"); ui->treeWidget->setUpdatesEnabled(true); //This is working only in the constructor QAbstractItemModel* const mdl= ui->treeWidget->model(); const int rowCount =mdl->rowCount(); if(mdl->insertRow(rowCount)){ qDebug("Row Inserted!"); if(mdl->setData(mdl->index(rowCount,0),"Pepedfsdf")) qDebug("Pepedfsdf Written"); if(mdl->setData(mdl->index(rowCount,1),"Descdfsdfsdf")) qDebug("Descdfsdfsdf Written"); } //This is working only in the constructor QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui->treeWidget); treeItem->setText(0, "Pepedfsdf"); treeItem->setText(1, "Descdfsdfsdf"); } TreeNodesUI::~TreeNodesUI() { delete ui; } //Take a look at the comments //IGNORE THE INPUT PARAMETERS--------------------------------------------------- void TreeNodesUI::addTreeChild(Node *node_to_add, QString name, QString description) { //ALL INSERTED HERE WILL NOT WORK (its called in some point of the program, I debug this) QAbstractItemModel* const mdl= ui->treeWidget->model(); const int rowCount =mdl->rowCount(); if(mdl->insertRow(rowCount)){ qDebug("Row Inserted!"); if(mdl->setData(mdl->index(rowCount,0),"Pepedfsdf")) qDebug("Pepedfsdf Written"); if(mdl->setData(mdl->index(rowCount,1),"Descdfsdfsdf")) qDebug("Descdfsdfsdf Written"); } //Another test QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui->treeWidget); treeItem->setText(0, "Pepedfsdf"); treeItem->setText(1, "Descdfsdfsdf"); //With some probes calling updates functions ui->treeWidget->repaint(); QWidget::update(); repaint(); return; }
-
Don't mix the APIs
#include "treenodesui.h" #include "ui_treenodesui.h" #include <QStringList> #include <QAbstractItemModel> TreeNodesUI::TreeNodesUI(QWidget *parent) : QWidget(parent), ui(new Ui::TreeNodesUI) { ui->setupUi(this); ui->treeWidget->setColumnCount(2); ui->treeWidget->setHeaderLabels(QStringList() << "Name" << "Type"); //This is working only in the constructor QAbstractItemModel* const mdl= ui->treeWidget->model(); const int rowCount =mdl->rowCount(); if(mdl->insertRow(rowCount)){ qDebug("Row Inserted!"); if(mdl->setData(mdl->index(rowCount,0),"Pepedfsdf")) qDebug("Pepedfsdf Written"); if(mdl->setData(mdl->index(rowCount,1),"Descdfsdfsdf")) qDebug("Descdfsdfsdf Written"); } } TreeNodesUI::~TreeNodesUI() { delete ui; } //Take a look at the comments //IGNORE THE INPUT PARAMETERS--------------------------------------------------- void TreeNodesUI::addTreeChild(Node *node_to_add, QString name, QString description) { QAbstractItemModel* const mdl= ui->treeWidget->model(); const int rowCount =mdl->rowCount(); if(mdl->insertRow(rowCount)){ qDebug("Row Inserted!"); if(mdl->setData(mdl->index(rowCount,0),"Pepedfsdf")) qDebug("Pepedfsdf Written"); if(mdl->setData(mdl->index(rowCount,1),"Descdfsdfsdf")) qDebug("Descdfsdfsdf Written"); } }
-
@VRonin said in Use QTreeWidget with non-static data.:
Don't mix the APIs
I don't really understand what I did wrong, mix the APIs? Where? I copy-paste your code and still doesn't work. What should I add in addTreeChild to work? @VRonin, you put the same code as me. I have the conclusion that the QTreeWidget only admit new rows in the constructor, all after this will not display. So if you have any simple code or project to add items (i.e. when you click a button inserts a new row) please explain me how
-
@ZiketCPP said in Use QTreeWidget with non-static data.:
mix the APIs?
You were using the QTreeItem API, I used the QAbstractItemModel one.
I have the conclusion that the QTreeWidget only admit new rows in the constructor
this clearly can't be. QTreeWidget doesn't even know you are in a constructor.
can you try this minimal example?
#include <QApplication> #include <QWidget> #include <QTreeWidget> #include <QAbstractItemModel> #include <QVBoxLayout> int main(int argc, char *argv[]) { QApplication app(argc,argv); QWidget wid; QPushButton* addTreeBtn=new QPushButton("Add Row",&wid); QTreeWidget* treeWid=new QTreeWidget(&wid); treeWid->setColumnCount(2); treeWid->setHeaderLabels(QStringList() << "Name" << "Type"); QObject::connect(addTreeBtn,&QPushButton::clicked,treeWid,[treeWid](){ QAbstractItemModel* const mdl= treeWid->model(); const int rowCount =mdl->rowCount(); if(mdl->insertRow(rowCount)){ qDebug("Row Inserted!"); if(mdl->setData(mdl->index(rowCount,0),"Pepedfsdf")) qDebug("Pepedfsdf Written"); if(mdl->setData(mdl->index(rowCount,1),"Descdfsdfsdf")) qDebug("Descdfsdfsdf Written"); } }); QVBoxLayout* widlay=new QVBoxLayout(&wid); widlay->addWidget(addTreeBtn); widlay->addWidget(treeWid); wid.show(); return app.exec(); }
-
-
It's incredible, it only displays the info if the info is called with any Signal/Slot function. If you try to do this for example in the update of your program (call a function that inserts a new Row) it will not work... Any idea why? Or any idea doing calling a function in the update for example? Thank you :D
-
@ZiketCPP said in Use QTreeWidget with non-static data.:
If you try to do this for example in the update
That's just an infinite loop.
Update inserts a row -> the view detects the row change -> the view calls update -> loop
-
@VRonin if you try to create a class with the functions
void InsertElement() { QAbstractItemModel* const mdl= treeWid->model(); const int rowCount =mdl->rowCount(); if(mdl->insertRow(rowCount)){ qDebug("Row Inserted!"); if(mdl->setData(mdl->index(rowCount,0),"Pepedfsdf")) qDebug("Pepedfsdf Written"); if(mdl->setData(mdl->index(rowCount,1),"Descdfsdfsdf")) qDebug("Descdfsdfsdf Written"); } }
Insert this in any class with an UI file (with the TreeWidget), if you don't insert the elements using the Signal/Slot this does not work
-
Where do you call
InsertElement
from? -
@VRonin from the update function (for example), try it, remember my code (I posted it in this discussion), it does not work. You only can update the TreeWidget if you insert rows inside Slot/Signal function.... try it, really
-
update function
That's too generic.
You only can update the TreeWidget if you insert rows inside Slot/Signal function
Signals and slots are just terms used by
moc
that then converts them into pure C++. there is no difference between a slot and a normal method/function:#include <QApplication> #include <QWidget> #include <QTreeWidget> #include <QAbstractItemModel> #include <QVBoxLayout> void insertRow(QAbstractItemModel* const mdl){ const int rowCount =mdl->rowCount(); if(mdl->insertRow(rowCount)){ qDebug("Row Inserted!"); if(mdl->setData(mdl->index(rowCount,0),"Pepedfsdf")) qDebug("Pepedfsdf Written"); if(mdl->setData(mdl->index(rowCount,1),"Descdfsdfsdf")) qDebug("Descdfsdfsdf Written"); } } int main(int argc, char *argv[]) { QApplication app(argc,argv); QWidget wid; QTreeWidget* treeWid=new QTreeWidget(&wid); treeWid->setColumnCount(2); treeWid->setHeaderLabels(QStringList() << "Name" << "Type"); for(int i=0;i<10;i++){ insertRow(treeWid->model()); } QVBoxLayout* widlay=new QVBoxLayout(&wid); widlay->addWidget(addTreeBtn); widlay->addWidget(treeWid); wid.show(); return app.exec(); }
My guess is that you are blocking the event loop somehow
-
@VRonin all of this is before the update/draw happens (in the wid.show() function), if you do this while the program is running, in the UPDATE function of the program, this function "insertRow()" won't work. Ok, I will try to explain myself.
Try to call this function in the main loop of the render for example. I don't know if the class MainWindow has an update function and u can override it. -
@VRonin take a care that all u did is before the show() function or is inside the Signal/Slot button function that you created.
-
in the main loop of the render for example.
What render do you mean ?
Qt is controlled by events which are distributed with this function
return app.exec(); << loops around here
http://doc.qt.io/qt-5/qapplication.html#execSo if you mean it only works if you let the the event loop run, you are correct.
if you make a tight for loop and never leave it, it cannot work.If you create a button
void MainWindow::on_pushButton_clicked() { for(;;); }
You will have 100% killed the program and it cant move or draw itself.
Also its perfectly fine to show the widget first then add Items.
int main(int argc, char *argv[]) { QApplication app(argc,argv); QWidget wid; wid.show(); // show first QTreeWidget* treeWid=new QTreeWidget(&wid); treeWid->setColumnCount(2); treeWid->setHeaderLabels(QStringList() << "Name" << "Type"); for(int i=0;i<10;i++){ insertRow(treeWid->model()); } QVBoxLayout* widlay=new QVBoxLayout(&wid); widlay->addWidget(treeWid); return app.exec(); // first here it will be drawn anyway }
Also a slot function is a normal c++ function.
There is no difference.So if you call it insertRow from somewhere and its not working, its either a
plain bug OR you are blocking the event loop by use for/while statement that
never terminates. ( as VRonin says)Inserting rows works outside constructors and member functions used as slot.
If you see otherwise, please post the whole code where you call
insertRow and we can try help spot what is going on. -
@mrjj no, i am not blocking the update. One question, with the @VRonin code, is there a possibilitty to call via c++ the pushButton->clicked() function? If you connect the click function to the lambda and then u call PushButton->clicked() nothing will appear in the tree (supposedly it would have to appear one row).
If this can be, how can I pass user data throw the function, as a parameter? Thank you!!!!