c0nn
c0nn

Reputation: 327

Printing to an element of MainWindow from an outside class

I have created a set of watcher/helper classes that monitor an outside application, and I would like these to print to a log window inside my MainWindow's ui when changes are made. My idea was to create this watcher inside a thread in main, but I am not sure the best way to link it to my MainWindow. I know that simply passing it as below will not work, but am unsure of the proper way to do this, if there even is one, because of Qt's design. Some research indicated to me that it isn't really appropriate to pass MainWindow to an outside class, but I am unsure of a better way to do it.

int main(int argc, char *argv[])
{
    try {
        std::string host = "localhost";
        unsigned short port = 8193;
        MainWindow w;
        w.show();

        // Access class for the program that I am watching
        UserInterface ui(host, port);
        // StatePrinter class, which is registered in the UI and will print changes to MainWindow, ideally
        // would I be able to pass something in the StatePrinter constructor to accomplish my goal?
        ui.registerObserver(new StatePrinter(w));
        UiRunner runner(ui);
        boost::thread runnerThread(boost::ref(runner));

        w.show();
        QApplication a(argc, argv);

        runner.cancel();
        runnerThread.join();

        return a.exec();
    } catch(std::exception &ex) {
        // ...
    }
}

I suppose it is a possibility to make this thread inside MainWindow itself, but I prefer having it in main. What would be the best way to link my StatePrinter class to MainWindow?

Upvotes: 1

Views: 74

Answers (2)

Dmitry Sazonov
Dmitry Sazonov

Reputation: 9014

You have several problems:

  1. Creating widgets before instance of QApplication
  2. runnerThread.join call will block main Qt thread before entering Qt event loop - so your GUI will be freezed

You should implement notification system to watch for termination of boost threads. But better solution is to use Qt threads.

  1. You should create first class - "watcher" with neccessary signals.
  2. Then create second class with UI logic and neccessaty slots
  3. Then connect signals to slots
  4. Profit!

Look at Qt documentation about QThread - there are simple samples.

Upvotes: 1

JBL
JBL

Reputation: 12907

You could make your watcher class a QObject itself, push it into a thread, and make it emit signals when it "notices" changes that you want to log with the log informations as the signal parameters.

Then, you could push this object in a QThread as follow :

QThread* thread = new QThread();
ui->moveToThread(thread);

//Create the needed connections

thread->start();

Depending on what you need, you may connect a signal to the thread's start() slot instead of calling it directly. (Read this to know which connections you'll need with your thread so it is started, stopped and cleaned correctly).

Upvotes: 2

Related Questions