called show(),label does not appear until a heavy work function finished
-
Hi all, I was trying to add a a label in front of mainwidgets to remind my user that my progrom still work.
However, the lebel only appear after that heavy work function finished its work. Here is my code, how to improve that?
If I called delete that label, the label would not show. However, if I did not called delete, that label only showes after the function finished.
Edit:
I will try the QStyledItemDelegate at the weekend, perhep it work.
After my quick testing, the two setCellWidget() spend close to70% running time, and connect only spend 25% running time. This is sick to make so many living widgets.
void Werahouse::on_query_clicked() { //appear the label QLabel *a = new QLabel("查询中!!!!!",this); a->setGeometry(370,340,430,200); QFont font = a->font(); font.setPointSize(20); font.setBold(true); a->setFont(font); a->show();//where show called //some sql quary not matter QString data = transdate(ui->dateEdit->date()); QString banci = transNull(ui->banci->currentText()); QSqlQuery query(db); query.exec("DROP TABLE IF EXISTS temp_tb;"); query.exec("CREATE TEMPORARY TABLE temp_tb SELECT * FROM `"+tablename+"` WHERE `日期` = '"+data+"' AND `班次` = '"+banci +"' ; "); query.exec("ALTER TABLE temp_tb DROP `上传日期`,DROP`日期`,DROP`班次`;"); query.exec("SELECT * FROM temp_tb;");//多句sql要多句exec执行 model->setQuery(query); cleantable(); if(fullpage){ RowPerPage = model->rowCount(); }else{ RowPerPage = ui->pagenumlineEdit->text().toInt(); if(RowPerPage> model->rowCount()){ RowPerPage = model->rowCount(); ui->pagenumlineEdit->setText(QString(QString::number(RowPerPage))); } } //above are some sql quary not matter readmodel(); // the heavy work function take a long time // delete a; //if I called delete, the label would not show, however, I did not called it, label only showes after the function finished } void Werahouse::readmodel(){ int Colcount = model->rowCount(); for(int i = 0;i<RowPerPage;i++){ ui->tableWidget->setRowCount(ui->tableWidget->rowCount() + 1); for(int j =0;j <Colcount;j++) ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, j, new QTableWidgetItem(model->record(i).value(j).toString())); // 在 y = ui->tableWidget->rowCount() - 1 // x = j //输入 new QTableWidgetItem(model->record(i).value(j).toString()) //model->record(i).value(j).toString() linkComboBox* myComboBox1 = new linkComboBox(&werahouseVector); for(int j = 0;j <werahouseVector.size() ;j++) myComboBox1->addItem(werahouseVector[j][0]); linkComboBox* myComboBox2 = new linkComboBox(&werahouseVector); for(int j = 1;j <werahouseVector[0].size() ;j++) myComboBox2->addItem(werahouseVector[0][j]); connect(myComboBox1,QOverload<int>::of(&QComboBox::currentIndexChanged),myComboBox2,&linkComboBox::changed); ui->tableWidget->setCellWidget ( ui->tableWidget->rowCount() - 1, 8,myComboBox1); ui->tableWidget->setCellWidget ( ui->tableWidget->rowCount() - 1, 9,myComboBox2); } // the reason why function takes time, it connected over thousands combobox }
-
@hehedaozuiteng Well, your heavy work blocks the event loop, that's why you see the label after the work is done - when the event loop is processing again.
You could call https://doc.qt.io/qt-5/qcoreapplication.html#processEvents after show() to give the event loop a chance to show your label, but this is not a nice solution.For what you're trying to achieve it would be better to use https://doc.qt.io/qt-5/qprogressdialog.html instead of a label.
-
@hehedaozuiteng said in called show(),label does not appear until a heavy work function finished:
If I make a qthread to create label
Don't do that! It is not supported.
GUI classes can only be created and accessed in GUI thread (the one calling QApplication::exec() in main).It should be other way around: move your heavy work to other thread.
-
@hehedaozuiteng said in called show(),label does not appear until a heavy work function finished:
The heavy work is I called connected() over thousand times. I guess it is not supported also ?
What connected() do you mean?
-
@hehedaozuiteng The connect itself should not take time as it does almost nothing (it just connects signal to slot).
You probably mean that linkComboBox::changed takes time? But I don't know what it is doing.
And of course you should not connect same signal to same slot over thousend times :-) -
Sorry, I just start QT at last Christmas, so I do not have a good exprience on it. I truly believe connect() is the reason takes time.
function changed() just changed items inside of comboBox.
void linkComboBox::changed(int index){ this->clear(); for (int i = 1;i<werahouseVector->at(index).count();i++) { this->addItem(werahouseVector->at(index)[i]); } }
I called connect over thousand is because of there are handrands combobox I created in one tablewidget. They are actually thousands different pairs of points.
-
I called connect over thousand is because of there are handrands combobox I created in one tablewidget.
connect()
should take "little" time. 1,000connect()
s should not be noticeable.Think again about whether you mean it's the
connect()
s that are taking time or the execution of the slot. Your slot clears out a combobox and then adds an unknown number of elements back in. That is, or could be, a (relatively) "slow" operation, though if it's only called once in response to one combobox changing it should be minor.You really should not be creating 1,000 comboboxes in a
QTableWidget
. You should be accomplishing the desired behaviour by using aQStyledItemDelegate
instead of having live widgets all over the table. If @VRonin sees this, he may offer freely offer you code to change this behaviour.... :)EDIT I am a little concerned at your used of slot for https://doc.qt.io/qt-5/qcombobox.html#currentIndexChanged clearing out and resetting combobox content:
This signal is sent whenever the currentIndex in the combobox changes either through user interaction or programmatically. The item's index is passed or -1 if the combobox becomes empty or the currentIndex was reset.
Since that includes "programmatically", when you clear the items that should reset
currentIndex
to -1. Which, unless a Qt expert says otherwise, should cause yourchanged()
slot to be called a second time. It probably settles down after that second call, ascurrentIndex
then stays on -1, sochanged()
does not get called yet again. Meanwhile, your code will not work ifindex == -1
. Put in aqDebug()
/use a debugger to see whether this is indeed occurring? -
@JonB said in called show(),label does not appear until a heavy work function finished:
StyledItemDelegat
thanks for your reply, you are right, the connect() just a last straw. The true reason is the size of the table, and living Widget combotable. Sorry for misslead, I am stupided.
QStyledItemDelegate maybe a solution. (by creating a widget which contain two connected comboboxes.) It a little bit complax for me, will try it weekend( at school).
-
@hehedaozuiteng From my experience I would guess that it is not the
connect
that takes a lot of time, but instead it is callingnew
to create theQComboBoxes
in the first place.I'd like to add that using a
QStyledItemDelegate
is a good choice in general. However, it is not exactly the same: You would display the current value in each table cell at the beginning. Only after starting an edit (by double clicking or pressing F2 on a selected cell) will the combo box appear. Still, in order to get the value into the table cell you would callnew
to create aQTableWidgetItem
instead of theQComboBox
. If I am right aboutnew
being the problem in the first place, this approach alone would not improve performance.This would finally leave you with a
QTableView
and subclassingQAbstractItemModel
. The table view would only query the information from the model for the visible cells. This could then be combined with theQStyledItemDelegate
. If, however, you still want to see the combo boxes directly, it might work to subclassQTableView
to instatiate combo boxes directly from the model.