How to show progress bar before show Dialog.
-
I have class SimpleProgressBar about (QLabel and QProgressBar)
SimpleProgressBar .h
class SimpleProgressBar : public QDialog { Q_OBJECT public: explicit SimpleProgressBar(QWidget *parent = 0); ~SimpleProgressBar(); void SetContent(QString text); private: Ui::SimpleProgressBar *ui; };
SimpleProgressBar .cpp
SimpleProgressBar::SimpleProgressBar(QWidget *parent) : QDialog(parent), ui(new Ui::SimpleProgressBar) { ui->setupUi(this); } SimpleProgressBar::~SimpleProgressBar() { delete ui; } void SimpleProgressBar::SetContent(QString text) { ui->label->setText(text); }
One class TableDialog
TableDialog.hclass TableDialog : public QDialog { Q_OBJECT public: explicit TableDialog(QWidget *parent = 0); ~TableDialog(); void loadDataTable(QStringList listData); private: Ui::TableDialog *ui; };
TableDialog.cpp
TableDialog::TableDialog(QWidget *parent) : QDialog(parent), ui(new Ui::TableDialog) { ui->setupUi(this); } TableDialog::~TableDialog() { delete ui; } void TableDialog::loadDataTable(QStringList listData) { QString checkBoxStyle = "margin-left:25%; margin-right:20%;"; for (int i = 0; i < listData.size(); i++) { QCheckBox *m_checkbox = new QCheckBox; m_checkbox->setStyleSheet( checkBoxStyle ); m_checkbox->setChecked(false); QTableWidgetItem *itemName = new QTableWidgetItem; QTableWidgetItem *index = new QTableWidgetItem; itemName->setText(listData.at(i)); index->setText(QString::number(i+1)); index->setTextAlignment(Qt::AlignCenter); m_checkbox->setFocusPolicy( Qt::NoFocus ); ui->tableWidget->setItem(i,0,index); ui->tableWidget->setCellWidget(i,1,m_checkbox); ui->tableWidget->setItem(i, 2 ,itemName); } }
And dialog main MyDialog (include TableDialog and SimpleProgressBar)
MyDialog.hclass MyDialog : public QDialog { Q_OBJECT public: explicit MyDialog(QWidget *parent = 0); ~MyDialog(); private slots: void on_pushButton_clicked(); void finishAndShowDialog(); private: Ui::MyDialog *ui; QFutureWatcher<void> FutureWatcher; SimpleProgressBar* m_progressBar; TableDialog *dialogTable; };
MyDialog.cpp
MyDialog::MyDialog(QWidget *parent) : QDialog(parent), ui(new Ui::MyDialog) { ui->setupUi(this); m_progressBar = NULL; dialogTable = NULL; } MyDialog::~MyDialog() { delete ui; } void MyDialog::on_pushButton_clicked() { if(m_progressBar == NULL) { this->m_progressBar = new SimpleProgressBar(this); } else { delete m_progressBar; m_progressBar = NULL; this->m_progressBar = new SimpleProgressBar(this); } if(dialogTable != NULL) { delete dialogTable; dialogTable = NULL; } dialogTable = new TableDialog; QStringList listData; for (int i = 0; i < 5000; i++) { listData.push_back("Thanh "+i); } FutureWatcher.setFuture(QtConcurrent::run(dialogTable,&TableDialog::loadDataTable,listData)); connect(&FutureWatcher, SIGNAL (finished()), this, SLOT (finishAndShowDialog())); m_progressBar->SetContent("Please waiting...."); this->m_progressBar->show(); } void MyDialog::finishAndShowDialog() { m_progressBar->close(); dialogTable->show(); }
I run the application but it fails when click button.Please show me how to use that right progress bar! Thank u.
-
You cannot access UI related stuff in a different thread. UI can only be changed in the same thread as QApplication::exec().
You start TableDialog::loadDataTable in a different thread. This is the first thing to change.
You can execute heavy calculations in a different thread, but you should not manipulate the UI from that thread. Instead you can use signals and slots to pass data between the two threads (use queued connection). -
Thank jsulm. Please can you help me make an example of it .
-
Why do you call TableDialog::loadDataTable() in a different thread?
All it does is to populate your table, so there is no need to call it in a different thread. -
I'm sorry, I understand. Because I dont know to create an other thread run TableDialog::loadDataTable() .
-
what is the issue you are facing ? Is it not showing the table ? Or progress bar is not shown ?
- One potential issue is about the QCheckBox created in different thread.
- You are running load table in different thread and queing the vector list. This may give problem.
Please do let us know what is exact issue. I can share you the sample which make it work.
-
Thank u. Progress bar is shown, but dialog table not show and show error QWidget: "Widgets must be created in the GUI thread."
-
@HAHAHAHAHA As I sad: you should not manipulate UI in a different thread! This is not going to work.
-
Yes. This is the potential problem i was hihlighting. You are calling load function which is executed in different thread. In load function you are creating the QCheckBox which is UI object. So it must be falling. This is nothing do with your progress bar. You should create those UI object in main thread itself. Hope this clarifies.
You can make simple change like the following to make it work without threads or QtConcurrent
void MyDialog::on_pushButton_clicked() {
// FutureWatcher.setFuture(QtConcurrent::run(dialogTable,&TableDialog::loadDataTable,listData));
// connect(&FutureWatcher, SIGNAL (finished()), this, SLOT (finishAndShowDialog()));
m_progressBar->SetContent("Please waiting....");
this->m_progressBar->show();
connect(dialogTable, SIGNAL (finished()), this, SLOT (finishAndShowDialog()));
dialogTable->loadDataTable(listData);
}class TableDialog : public QDialog
{
Q_OBJECTpublic:
explicit TableDialog(QWidget *parent = 0);
~TableDialog();
void loadDataTable(QStringList listData);
void test();signals :
void finished();
...
}void TableDialog::loadDataTable(QStringList listData)
{
QString checkBoxStyle = "margin-left:25%; margin-right:20%;";
for (int i = 0; i < listData.size(); i++)
{
qDebug() << " Loading the Data ="<<i <<endl;
QCheckBox *m_checkbox = new QCheckBox;
m_checkbox->setStyleSheet( checkBoxStyle );
m_checkbox->setChecked(false);
......
}
emit finished();
} -
Thanks everyone. :))
-
Cool. You can put this qn to SOLVED state. Also upvote if any of our answer helped you fix the issue.