QProgressBar and ActiveX
-
With Qt Creator, I have inserted a progress bar using the QProgressBar object. I would like the progress bar displaying the busy mode while doing some operations in Excel ( called via ActiveX)
If I am not wrong QAxObject will start another thread so the GUI should not hang out during the ActiveX call/operations. Could you tell me what I did wrong ?
Here is my code
// progressBar busy mode ui->progressBar->setMinimum(0); ui->progressBar->setMaximum(0); ui->progressBar->show(); // Kick Excel using ActiveX CoInitialize(0); QAxObject excel( "Excel.Application", 0 ); //Some Excel operations... during few seconds // Quit Excel excel.dynamicCall("Quit()"); // Revert to normal mode ui->progressBar->setMaximum(100);
-
Hi, while QAxObject can do many fancy things, starting another thread outside of the GUI is not of them :-(
But if you add some QThread/worker code and move the QAxObject stuff in there, it will work nicely with the GUI.
Here's an example that updates a progress bar: create an empty vanilla Widget app, add axcontainer to the QT line in the .pro file, then change mainwindow.h to this:#include <QMainWindow> #include "windows.h" // for the CoInitialize() call #include "QAxObject" #include <QThread> namespace Ui { class MainWindow; } class ExcelWorker : public QObject { Q_OBJECT public slots: void doWork(int n) { CoInitialize(0); auto excel = new QAxObject("Excel.Application",0); if (nullptr == excel) return; excel->setProperty("Visible",true); auto workbooks = excel->querySubObject("Workbooks"); auto workbook = workbooks->querySubObject("Add"); auto sheets = workbook->querySubObject("Worksheets"); auto sheet = sheets->querySubObject("Item(int)",1); for (int i = 0; (i < n); ++i) { sheet->querySubObject("Cells(int,int)",i % 10 + 1,i / 10 + 1)->setProperty("Value",i); QThread::msleep(100); // simulate some heavy munging emit oneReady(i); } } signals: void oneReady(int i); }; class MainWindow : public QMainWindow { Q_OBJECT QThread excelThread; public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void oneReadyFromExcel(int i); void on_pushButton_clicked(); signals: void doExcelWork(int n); private: Ui::MainWindow *ui; };
and change the mainwindow.cpp to this:
#include "mainwindow.h" #include "ui_mainwindow.h" #include "qtimer.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); auto ew = new ExcelWorker; ew->moveToThread(&excelThread); connect(this,&MainWindow::doExcelWork,ew,&ExcelWorker::doWork); connect(ew,&ExcelWorker::oneReady,this,&MainWindow::oneReadyFromExcel); excelThread.start(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_clicked() { emit doExcelWork(100); } void MainWindow::oneReadyFromExcel(int i) { ui->progressBar->setValue(i); }
Finally add one progress bar and a push button and connect the clicked() signal from the push button to starting Excel and you're good to go.
Edit: I just tested it, it runs ok but crashes when exiting the app, the example is missing the cleanup of the worker thread and quitting Excel, but I think you'll get the idea anyhow..