Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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
    
    
    }
    

  • Qt Champions 2019

    @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.



  • @jsulm
    Thank you very much, I solved it by QProgressDialog.

    Last question, If I make a qthread to create label, can it escape the heavy work blocks the even loop? any suggestion.


  • Qt Champions 2019

    @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.



  • @jsulm ,

    Thank you for your suggestion.
    The heavy work is I called connected() over thousand times. I guess it is not supported also ? I have to figure a way out by myself.


  • Qt Champions 2019

    @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?



  • @jsulm
    connect() my bad.
    it connected two ComboBox. it takes time.

    connect(myComboBox1,QOverload<int>::of(&QComboBox::currentIndexChanged),myComboBox2,&linkComboBox::changed);
    

  • Qt Champions 2019

    @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 :-)



  • @jsulm

    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.



  • @hehedaozuiteng

    I called connect over thousand is because of there are handrands combobox I created in one tablewidget.

    connect() should take "little" time. 1,000 connect()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 a QStyledItemDelegate 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 your changed() slot to be called a second time. It probably settles down after that second call, as currentIndex then stays on -1, so changed() does not get called yet again. Meanwhile, your code will not work if index == -1. Put in a qDebug()/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).



  • @jsulm

    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.



  • @hehedaozuiteng From my experience I would guess that it is not the connect that takes a lot of time, but instead it is calling new to create the QComboBoxes 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 call new to create a QTableWidgetItem instead of the QComboBox. If I am right about new being the problem in the first place, this approach alone would not improve performance.

    This would finally leave you with a QTableView and subclassing QAbstractItemModel. The table view would only query the information from the model for the visible cells. This could then be combined with the QStyledItemDelegate. If, however, you still want to see the combo boxes directly, it might work to subclass QTableView to instatiate combo boxes directly from the model.


Log in to reply