How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?
-
Hi,
There is a QTableView, associated with a QStandardItemModel in my program. I run into an issue that the program is hanging up about 2 seconds when loading files and refresh UI. Most of time is spent in a function to create QStandardItems and set it into model. After disconnecting all the signals of the model, the UI is refreshed fluently.
myStandardItemModel->disconnect();And I can confirm that this issue is not caused by my customized signal because it doesn't work to disconnect it. SO... how many inner signals are triggered here? Is it possible to disconnect and re-connect them when I'd like to?
Thanks in advance.
-
Hi,
There is a QTableView, associated with a QStandardItemModel in my program. I run into an issue that the program is hanging up about 2 seconds when loading files and refresh UI. Most of time is spent in a function to create QStandardItems and set it into model. After disconnecting all the signals of the model, the UI is refreshed fluently.
myStandardItemModel->disconnect();And I can confirm that this issue is not caused by my customized signal because it doesn't work to disconnect it. SO... how many inner signals are triggered here? Is it possible to disconnect and re-connect them when I'd like to?
Thanks in advance.
@Lee908 said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
SO... how many inner signals are triggered here?
You/we don't know.
You could try
myStandardItemModel->blockSignals(true)(orQSignalBlockerfor convenience) across "loading" to see how that behaves.I would not expect your set up to take a "long time" ("hanging up about 2 seconds") unless either you are loading a lot of data (just how much data are you loading?) or you have some of your own code running on signals.
-
@Lee908 said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
SO... how many inner signals are triggered here?
You/we don't know.
You could try
myStandardItemModel->blockSignals(true)(orQSignalBlockerfor convenience) across "loading" to see how that behaves.I would not expect your set up to take a "long time" ("hanging up about 2 seconds") unless either you are loading a lot of data (just how much data are you loading?) or you have some of your own code running on signals.
@JonB said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
You could try myStandardItemModel->blockSignals(true)
I also considered that solution. But it caused some data were not refreshed in UI.
how much data are you loading?
2000 rows, 7 columns...
-
@JonB said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
You could try myStandardItemModel->blockSignals(true)
I also considered that solution. But it caused some data were not refreshed in UI.
how much data are you loading?
2000 rows, 7 columns...
@Lee908 said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
I also considered that solution. But it caused some data were not refreshed in UI.
In a sense does not surprise me, in another post this morning I wrote that I don't trust
blockSignals()not to mess up something by blocking all signals!2000 rows, 7 columns...
Although 2,000 rows is quite a lot to show to the user in a table, I am still "surprised" this takes "2 seconds", but maybe so. OoI, what is your user going to do with 2,000 visually-presented rows?
-
@Lee908 said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
I also considered that solution. But it caused some data were not refreshed in UI.
In a sense does not surprise me, in another post this morning I wrote that I don't trust
blockSignals()not to mess up something by blocking all signals!2000 rows, 7 columns...
Although 2,000 rows is quite a lot to show to the user in a table, I am still "surprised" this takes "2 seconds", but maybe so. OoI, what is your user going to do with 2,000 visually-presented rows?
@JonB said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
OoI, what is your user going to do with 2,000 visually-presented rows?
Surprised!!! Do you mean it can't support 2,000 visually-presented rows fluently in Qt???...
-
@JonB said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
OoI, what is your user going to do with 2,000 visually-presented rows?
Surprised!!! Do you mean it can't support 2,000 visually-presented rows fluently in Qt???...
@Lee908
I am "surprised" 2,000 rows takes 2 seconds, but I have not tried it. My question is what your end user will want to do with 2,000 rows displayed visually in a table in front of him? That's quite a lot to take in, perhaps he will do a lot of scrolling and looking, I don't know. I have never presented a user with 2,000 rows to look through, that is all I am saying. -
@JonB said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
OoI, what is your user going to do with 2,000 visually-presented rows?
Surprised!!! Do you mean it can't support 2,000 visually-presented rows fluently in Qt???...
-
@JonB said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
OoI, what is your user going to do with 2,000 visually-presented rows?
Surprised!!! Do you mean it can't support 2,000 visually-presented rows fluently in Qt???...
-
@JonB said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
OoI, what is your user going to do with 2,000 visually-presented rows?
Surprised!!! Do you mean it can't support 2,000 visually-presented rows fluently in Qt???...
@Lee908
The following code:#include <QApplication> #include <QStandardItemModel> #include <QTableView> int main(int argc, char *argv[]) { QApplication a(argc, argv); QTableView tv; QStandardItemModel im; im.setColumnCount(7); for (int row = 0; row < 2000; row++) { QList<QStandardItem *> items; items.append(new QStandardItem(QString::number(row))); for (int col = 1; col < 7; col++) items.append(new QStandardItem(QString::number(col))); im.appendRow(items); } tv.setModel(&im); tv.show(); return a.exec(); }populates and shows 2,000 rows of 7 columns "instantaneously" on my very slow Linux box with Qt 5.15. What are you doing different from this?
-
@Lee908
The following code:#include <QApplication> #include <QStandardItemModel> #include <QTableView> int main(int argc, char *argv[]) { QApplication a(argc, argv); QTableView tv; QStandardItemModel im; im.setColumnCount(7); for (int row = 0; row < 2000; row++) { QList<QStandardItem *> items; items.append(new QStandardItem(QString::number(row))); for (int col = 1; col < 7; col++) items.append(new QStandardItem(QString::number(col))); im.appendRow(items); } tv.setModel(&im); tv.show(); return a.exec(); }populates and shows 2,000 rows of 7 columns "instantaneously" on my very slow Linux box with Qt 5.15. What are you doing different from this?
What are you doing different from this?
Your test is instantaneous is because you did setModel AFTER all items were created. Did you try it at beginning? Just take your example above, after your application 'tv' is displayed, user click a button to open file to load another 2000 rows into 'tv' (assumed there is a button). Guess if the loading work can be finished instantaneously or not?
Create/Edit data in the model which is been set into a table view, it will trigger some inner signals. That's the KEY POINT of this case!
-
@Lee908 since this, is like 14000 individual paint events all done via cpu, I'm not all to surprised by a visual delay in the update
@J-Hilk said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
since this, is like 14000 individual paint events all done via cpu, I'm not all to surprised by a visual delay in the update
@JonB 's demo has proved that it's not a problem for Qt to finish14000 individual paint events smoothly.
-
What are you doing different from this?
Your test is instantaneous is because you did setModel AFTER all items were created. Did you try it at beginning? Just take your example above, after your application 'tv' is displayed, user click a button to open file to load another 2000 rows into 'tv' (assumed there is a button). Guess if the loading work can be finished instantaneously or not?
Create/Edit data in the model which is been set into a table view, it will trigger some inner signals. That's the KEY POINT of this case!
@Lee908 said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
Did you try it at beginning?
Yes, I had already done that:
#include <QApplication> #include <QStandardItemModel> #include <QTableView> #include <QTimer> int main(int argc, char *argv[]) { QApplication a(argc, argv); QTableView tv; QStandardItemModel im; im.setColumnCount(7); tv.setModel(&im); tv.show(); QTimer::singleShot(0, [&im]() { for (int row = 0; row < 2000; row++) { QList<QStandardItem *> items; items.append(new QStandardItem(QString::number(row))); for (int col = 1; col < 7; col++) items.append(new QStandardItem(QString::number(col))); im.appendRow(items); } }); return a.exec(); }for example. Note how I let the table view be shown before I start appending rows. Same "fast" speed. So what have you tried? Try this and/or the previous one on your machine before analyzing any further,
-
@Lee908 said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
Did you try it at beginning?
Yes, I had already done that:
#include <QApplication> #include <QStandardItemModel> #include <QTableView> #include <QTimer> int main(int argc, char *argv[]) { QApplication a(argc, argv); QTableView tv; QStandardItemModel im; im.setColumnCount(7); tv.setModel(&im); tv.show(); QTimer::singleShot(0, [&im]() { for (int row = 0; row < 2000; row++) { QList<QStandardItem *> items; items.append(new QStandardItem(QString::number(row))); for (int col = 1; col < 7; col++) items.append(new QStandardItem(QString::number(col))); im.appendRow(items); } }); return a.exec(); }for example. Note how I let the table view be shown before I start appending rows. Same "fast" speed. So what have you tried? Try this and/or the previous one on your machine before analyzing any further,
-
@JonB said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
Same "fast" speed
Really SAME??? Before setModel and after setModel. Does it only happen on my old pc?
@Lee908
Yeah, "same" :)We need to be talking about the same code as each other, else all bets are off. Have you actually tried literally copying & pasting my two examples to yours? Do they differ for you? (I assume you do not have high start-up time.) Do either take you 2 seconds?
I just tried 20,000 rows instead of 2,000. Same "instantaneous"! Then 200,000, that was the first one which took about 1 or 2 seconds, and that's with 100x as many rows as yours :) And it requires 2,000,000 (two million) rows before it takes about 20 seconds....
-
Consider wrapping your changes to the model with beginResetModel() and endResetModel(). This should greatly reduce the updates needed when you add or remove cells one by one.
-
@Lee908
Yeah, "same" :)We need to be talking about the same code as each other, else all bets are off. Have you actually tried literally copying & pasting my two examples to yours? Do they differ for you? (I assume you do not have high start-up time.) Do either take you 2 seconds?
I just tried 20,000 rows instead of 2,000. Same "instantaneous"! Then 200,000, that was the first one which took about 1 or 2 seconds, and that's with 100x as many rows as yours :) And it requires 2,000,000 (two million) rows before it takes about 20 seconds....
@JonB said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
Do they differ for you?
Finding out the root cause!!! I set cells by calling setItem one by one, but not appendRow! After using appendRow, the time cost is basically the same whenever I set model. Thanks very much.
-
Consider wrapping your changes to the model with beginResetModel() and endResetModel(). This should greatly reduce the updates needed when you add or remove cells one by one.
-
@JonB said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
Do they differ for you?
Finding out the root cause!!! I set cells by calling setItem one by one, but not appendRow! After using appendRow, the time cost is basically the same whenever I set model. Thanks very much.
@Lee908 said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
I set cells by calling setItem one by one, but not appendRow!
Do you mean you had code like this:
im.insertRow(row); im.setItem(row, 0, new QStandardItem(QString::number(row))); for (int col = 1; col < 7; col++) im.setItem(row, col, new QStandardItem(QString::number(col)));With this my 2,000 items are still much faster than yours, but at 20,000 there is a noticeable delay.
Since you asked about "what signals are triggered", adding
QObject::connect(&im, &QStandardItemModel::rowsInserted, []() { qDebug() << "rowsInserted()"; }); QObject::connect(&im, &QStandardItemModel::itemChanged, []() { qDebug() << "itemChanged()"; }); QObject::connect(&im, &QStandardItemModel::dataChanged, []() { qDebug() << "dataChanged()"; });shows you the relevant signals here. With my
appendRow()of a built row there is only onerowsInserted()signal per row added. With your add-row-then-change-items there are additionally 7changedItem()anddataChanged()signals per each row, and these seem to be "expensive" in terms of what the table view does with them. @kkoehne'sbeginResetModel()(requires sub-classing) would avoid these signals, hence the speed, and perhaps desirable, but I would add the rows already filled with items in any case. -
@Lee908 said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
I set cells by calling setItem one by one, but not appendRow!
Do you mean you had code like this:
im.insertRow(row); im.setItem(row, 0, new QStandardItem(QString::number(row))); for (int col = 1; col < 7; col++) im.setItem(row, col, new QStandardItem(QString::number(col)));With this my 2,000 items are still much faster than yours, but at 20,000 there is a noticeable delay.
Since you asked about "what signals are triggered", adding
QObject::connect(&im, &QStandardItemModel::rowsInserted, []() { qDebug() << "rowsInserted()"; }); QObject::connect(&im, &QStandardItemModel::itemChanged, []() { qDebug() << "itemChanged()"; }); QObject::connect(&im, &QStandardItemModel::dataChanged, []() { qDebug() << "dataChanged()"; });shows you the relevant signals here. With my
appendRow()of a built row there is only onerowsInserted()signal per row added. With your add-row-then-change-items there are additionally 7changedItem()anddataChanged()signals per each row, and these seem to be "expensive" in terms of what the table view does with them. @kkoehne'sbeginResetModel()(requires sub-classing) would avoid these signals, hence the speed, and perhaps desirable, but I would add the rows already filled with items in any case.@JonB said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
Do you mean you had code like this:
I had a class inherited QStandardItemModel. Firstly, I wrapped a function to add items just like:
void MyTableModel::Update() { ... for(int i = 0; i < rowCount; i++) { QStandardItem* item1 = new QStandardItem("xx"); item1 ->setEditable(...); setItem(i, 0, item1 ); QStandardItem* item2 = new QStandardItem("xx"); item2 ->setFlags(...); setItem(i, 1, item2 ); ... QStandardItem* item7 = new QStandardItem("xx"); item7 ->setCheckable(...); setItem(i, 6, item7 ); } }After using appendRow instead of setItem, the time is shorter significantly.
beginResetModel() (requires sub-classing) would avoid these signals
How to avoid those signals? Can you provide me with some details?
-
@JonB said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
Do you mean you had code like this:
I had a class inherited QStandardItemModel. Firstly, I wrapped a function to add items just like:
void MyTableModel::Update() { ... for(int i = 0; i < rowCount; i++) { QStandardItem* item1 = new QStandardItem("xx"); item1 ->setEditable(...); setItem(i, 0, item1 ); QStandardItem* item2 = new QStandardItem("xx"); item2 ->setFlags(...); setItem(i, 1, item2 ); ... QStandardItem* item7 = new QStandardItem("xx"); item7 ->setCheckable(...); setItem(i, 6, item7 ); } }After using appendRow instead of setItem, the time is shorter significantly.
beginResetModel() (requires sub-classing) would avoid these signals
How to avoid those signals? Can you provide me with some details?
@Lee908 said in How many kinds of inner signals are triggered in Qt when modify item in QStandardItemModel?:
How to avoid those signals?
By calling beginResetModel(). As @JonB wrote you will need to subclass QStandardItemModel to be able to call it (it is a protected method).