Update 2 QTableWidgets simultaneously to reduce the run time
-
I have 2 sections which display data coming from same resource (basically the resource could be divided into two chunks) I measured each section run time as following 10ms filling data, 60ms drawing out result, 5ms, 30ms respectively. If only one thread can process UI that means 70ms + 35ms a total 105ms run time, ideally I prefer display the data seamlessly to reduce the total time to 70ms since 35ms is less than 70ms?
-
@Dev-G
As @Chris-Kawa told you in your other thread Qt does not allow access to the UI from multiple threads. That's just how it is, whether you like it or not.You can offload as much non-UI computation as you like to secondary threads, so if you can do that it may help. But such threads will have to send a signal to the main thread when it's ready for that to do whatever UI work with the results.
-
@JonB You mean Object.moveToThread(&someThread) then
QObject::connect(&someThread, &QThread::started, &myTableWidget, SLOT()); something like that?@JonB said in Update 2 QTableWidgets simultaneously to reduce the run time:
to do whatever UI work with the results.
Can you explain this in detail? I kind of confused with UI work and fill data into QTableWidget. For example, table->setItem(i, j, item) this consider UI work or data preparation? My understanding is data preparation, correct me if I am wrong.
-
@Dev-G
Nope, I'm afraid that is very much a "UI" call, and must never be done from a secondary thread. That could calculate what it is you want to put into the model data, but cannot call anything likeQTableWidget::setItem()
directly. The thread would have to emit a signal when the data was ready (either passed as an argument to the signal, or stored in some data structure which can safely be shared with the UI thread e.g. using a mutex). The UI must put a slot on that signal which when called picks up the data and puts it into theQTableWidget
for display.First things first. If you are concerned about speed you need to ditch
QTableWidget
. It is a "convenience" class for simple cases, not suitable for optimization. It does not do anything you cannot do yourself, and better. It comprises aQTableView
plus an in-built model of its own. Quite unsuitable for anything multi-threaded.So you will want to change over to a
QTableView
and attach that to your own model derived fromQAbstractItem
/TableModel
, which you design to be as convenient as possible to your data needs.To keep the secondary thread quite separate from anything UI, do not allow it to
#include
anything fromQWidget
orQGui
, either directly or via anything else of your own which includes them. You will soon find what you cannot use in this case!Take an example from me. I have been working on prime numbers. they are slow to generate (certainly as you get into the hundreds of billions!). Let's say I want to show a list of them and I can break the calculation into multiple separate, concurrent threads. Then these threads calculate one or a group of new numbers and emit a signal when new ones are available. The UI places a slot on this, and when called that puts them into the model and display them in the view.
-
J JonB referenced this topic on
-
@JonB Hi, what's the TableView + StandardModelItem like? I think I tried below model and TableView.
DashTableModel::DashTableModel()
{}
DashTableModel::~DashTableModel()
{}
QVariant DashTableModel::data(const QModelIndex &index, int role) const{
if (!index.isValid()) {
return QVariant();
}
if (role == Qt::TextAlignmentRole) {
return int(Qt::AlignLeft | Qt::AlignVCenter);
} else if (role == Qt::DisplayRole) {
return QStandardItemModel::data(index, role);
} else if (role == Qt::BackgroundRole) {} return QVariant();
}
=================================================================================
QTableView *tableView = new QTableView(widget);
tableView->setGeometry(10, 10, 400, 300);QStandardItemModel *model = new QStandardItemModel(); model->setRowCount(18); model->setColumnCount(28); model->setHeaderData(0, Qt::Horizontal, "Name"); model->setHeaderData(1, Qt::Horizontal, "Age"); model->setData(model->index(0, 0), "Tom"); model->setData(model->index(0, 1), 20); model->setData(model->index(1, 0), "Jerry"); model->setData(model->index(1, 1), 18); model->setData(model->index(2, 0), "Mike"); model->setData(model->index(2, 1), 25); tableView->setModel(model); QObject::connect(model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), tableView, SLOT(update()));
============================================================================
in the update() I will do something like below
model->setData(model->index(0, 0), "A"); model->setData(model->index(0, 1), 200); model->setData(model->index(1, 0), "B"); model->setData(model->index(1, 1), 180); model->setData(model->index(2, 0), "C"); model->setData(model->index(2, 1), 250);
It seems running slower than QTableWidget. What's wrong? Update() function should be triggered every 60ms using a Timer.
-
@Dev-G hi,
Why are you manually triggering updates of your view from your model ? It's already handled by Qt. What you are doing here is requesting additional repaints for nothing.
As for your technique, you are not doing things optimally for your end goal. You should rather take the time to understand how fast your data are coming in, how much of it will be useful for your user and more important, does it make any sense to fill your model and your view that fast for your users ? When you have fast inputs, it doesn't make any sense to try to show them as soon as they arrive. Work in batches, use a custom model and load several rows worth of data regularly rather than trying to push everything as fast as possible. You are not designing an MMO FPS.
-
@SGaist True, I am not doing a game development, but I need the program to be like 20FPS, I am doing some live monitoring which needs to refresh the screen frequently and very fast(closer to 20FPS). Here is some information to fill your question. The time relate to data(send request + receive data) is about 30ms which will be a uint8_t bit stream size over 1000 elements. NO JUNK in the source data.
You might say I could use plot to achieve monitoring feature, but that's just part of the monitoring. As you may find out from above, I need a table like heat map on the screen( I need to see each cell's value and color) I did try QCustomPlot's QCPColorMap, not ideal cuz I need to override some method in order to show value on QCPColorMap.
Does those information help?
-