Results 1 to 9 of 9

Thread: Create QMainWindow from different thread

  1. #1
    Join Date
    Feb 2015
    Posts
    3
    Qt products
    Qt5
    Platforms
    Windows

    Default Create QMainWindow from different thread

    Hey community,

    I try to create something like a window pool. You can use these windows everywhere in your program to display graphics and plot diagrams etc. The widgets working well but the main problem at the moment is the frustrated tries, to create the pool. One non QObject-Object should represent a QMainWindow to cut the bindings to Qt.

    I cannot create a widget -> I tried invokeMethode, connect and QTimer but nothing works. Sometimes the methods don´t get called or I am not in the gui thread... Any idea?

    header:

    Qt Code:
    1. #pragma once
    2. #include <QMainWindow>
    3.  
    4. class MyWindow : QObject
    5. {
    6. Q_OBJECT
    7. public:
    8. MyWindow();
    9. signals:
    10. void start();
    11. private:
    12. QWindow *mWin;
    13. };
    14.  
    15. class QWindowPool : public QObject
    16. {
    17. Q_OBJECT
    18. public:
    19. QWindowPool();
    20. public slots:
    21. void createWindow();
    22. };
    23.  
    24. class QWindow : public QMainWindow
    25. {
    26. Q_OBJECT
    27. };
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. #include <utils/MatWindow.h>
    2.  
    3. #include <QApplication>
    4. #include <QTimer>
    5.  
    6. #include <thread>
    7.  
    8. QWindowPool pool;
    9.  
    10. QWindowPool::QWindowPool()
    11. {
    12. int c = 0;
    13. new QApplication(c, NULL);
    14. }
    15.  
    16. void QWindowPool::createWindow()
    17. {
    18. printf("window created\n");
    19. new QWindow();
    20. }
    21.  
    22. MyWindow::MyWindow()
    23. {
    24. connect(this, SIGNAL(start()), &pool, SLOT(createWindow()));
    25. QTimer::singleShot(0, &pool, SLOT(createWindow()));
    26. QMetaObject::invokeMethod(&pool, "createWindow", Qt::BlockingQueuedConnection);
    27. emit start();
    28. }
    29.  
    30.  
    31. int main()
    32. {
    33. std::thread t1([](){
    34. MyWindow mw;
    35. qApp->processEvents(QEventLoop::AllEvents); // <- not working
    36. });
    37. // qApp->processEvents(QEventLoop::AllEvents); // work
    38. t1.join();
    39.  
    40. return 0;
    41. }
    To copy to clipboard, switch view to plain text mode 

    So, it does not work (createWindow does not get called) unless I uncomment the last processEvents in the main thread but that should not be the solution.

    What I want is in the final application: The user should get the possibility to write anywhere in his code and in any thread:
    Qt Code:
    1. MyWindow mw(dataToDisplay)
    To copy to clipboard, switch view to plain text mode 
    and the window should be created and showed to him. Currently it only works if he would call:
    Qt Code:
    1. qApp->processEvents(QEventLoop::AllEvents);
    To copy to clipboard, switch view to plain text mode 
    in the main thread. But I want do do this for him.... HOW?

    Thank you.

    BTW: I "cross posted" this question. First I asked at stackoverflow but didn´t get a right solution. http://stackoverflow.com/questions/2...fferent-thread
    Last edited by Viatorus; 20th February 2015 at 18:57.

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,012 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Create QMainWindow from different thread

    If you are not in the gui thread then in what thread are you? Widgets can only be accessed from the gui thread. If you want your methods to be callable from non-gui thread then you need to cross thread boundaries inside your calls (e.g. using signals and slots).
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Feb 2015
    Posts
    3
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Create QMainWindow from different thread

    Hello wysota,

    Thank you for your answer.

    My english must be really bad... sorry about that. But why do all people say the same: I know it!

    I KNOW: To call between non-gui threads and gui thread I have to use singal and slot.
    On line 24 to 27 what do you think I supposed to do? I use signal/slot principle.

    But this is not working without a call in the main thread... line 37

  4. #4
    Join Date
    Dec 2009
    Location
    New Orleans, Louisiana
    Posts
    791
    Thanks
    13
    Thanked 153 Times in 150 Posts
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: Create QMainWindow from different thread

    Quote Originally Posted by Viatorus View Post
    But this is not working without a call in the main thread... line 37
    Where are you creating an event loop and starting it by calling exec()? My understanding is that qApp->processEventLoop isn't the same as as running the event loop with exec().

    I don't believe you can have a true event loop without creating one of QCoreApplication or QApplication. Others know much better than me I am sure, so hopefully they can chime in and point you in the right direction.

    Good luck.

  5. #5
    Join Date
    Feb 2015
    Posts
    3
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Create QMainWindow from different thread

    Hey JThomps,

    You are right, I hoped to get it working without exec...
    The main problem for me at "qApp->exec()" is, it blocks the current thread. So when I would call it just before main get called, I would block the main thread. That is not an solution.
    My current versions looks like so:

    hpp:
    Qt Code:
    1. #pragma once
    2. #include <QMainWindow>
    3. #include <QTimer>
    4.  
    5. class MyWindow : QObject
    6. {
    7. Q_OBJECT
    8. public:
    9. MyWindow();
    10. };
    11.  
    12. class QWindowPool : public QObject
    13. {
    14. Q_OBJECT
    15. public:
    16. QWindowPool();
    17. public slots:
    18. void createWindow();
    19. };
    20.  
    21. class QWindow : public QMainWindow
    22. {
    23. Q_OBJECT
    24. };
    To copy to clipboard, switch view to plain text mode 

    cpp:
    Qt Code:
    1. #include <utils/MatWindow.h>
    2.  
    3. #include <QApplication>
    4. #include <QTimer>
    5. #include <QtConcurrent/qtconcurrentrun.h>
    6.  
    7. #include <iostream>
    8. #include <future>
    9.  
    10. static QWindowPool *pool = new QWindowPool();
    11.  
    12. QWindowPool::QWindowPool() {
    13.  
    14. // check if app is running
    15. if (!QApplication::instance()) {
    16. bool appOnline = false;
    17. QtConcurrent::run([&appOnline](){
    18. int c = 0;
    19. new QApplication(c, NULL);
    20. appOnline = true;
    21. qApp->exec();
    22. });
    23. while (!appOnline) {}
    24. }
    25. moveToThread(QApplication::instance()->thread());
    26. }
    27.  
    28. void QWindowPool::createWindow() {
    29. printf("window created\n");
    30. new QWindow();
    31. }
    32.  
    33. MyWindow::MyWindow() {
    34. QTimer::singleShot(0, pool, SLOT(createWindow()));
    35. }
    36.  
    37. int main()
    38. {
    39. MyWindow mw;
    40. std::thread t1([](){
    41. MyWindow mw;
    42.  
    43. std::thread t2([](){
    44. MyWindow mw;
    45. });
    46.  
    47. t2.join();
    48. });
    49. t1.join();
    50.  
    51. std::cin.ignore();
    52. return 0;
    53. }
    To copy to clipboard, switch view to plain text mode 

    Now the code do what is should. I can create widgets in different threads. But there are two scenarios, where I would stack at:
    1. Someone (anyone who would like to use this library) creates before me QApplication and never calls qApp->exec
    2. Someone want to create an own UI with Widget but does not work in my qt::concurrent gui thread. He would probably not get along with this.

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,012 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Create QMainWindow from different thread

    Quote Originally Posted by Viatorus View Post
    I KNOW: To call between non-gui threads and gui thread I have to use singal and slot.
    On line 24 to 27 what do you think I supposed to do? I use signal/slot principle.
    Line #26 won't work, as far as I remember.

    But this is not working without a call in the main thread... line 37
    It won't because for cross-thread signal-slot connections to work the receiving thread (in your case the GUI thread) has to be running an event loop.

    In general for Qt widgets to work you will need the main event loop running, so trying to work around having the main event loop is not really an option.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. #7
    Join Date
    Dec 2009
    Location
    New Orleans, Louisiana
    Posts
    791
    Thanks
    13
    Thanked 153 Times in 150 Posts
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: Create QMainWindow from different thread

    Quote Originally Posted by wysota View Post
    In general for Qt widgets to work you will need the main event loop running, so trying to work around having the main event loop is not really an option.
    Wysota, this is at least the 2nd time a similar thing has come up in the last week. Both cases the person is developing a library or API to be used by non-Qt applications and/or Qt applications and how to create/run an event loop seems to be the central problem.

    The reason they don't create an event loop when their API/library is called is because they then can't return to the caller if they create and exec an event loop on the same thread used to call into the API/library.

    Would it be possible to create a thread on the first library call that creates a QCoreApplication and exec()'s to enter an event loop in the newly created thread? The API/library method can return to the caller after creating and starting the thread and the thread would remain running with the QCoreApplication::exec() event loop.

    Queued signals/slots could then be used to communicate between the event loop thread and any future API/library calls made.

    Could this approach be used or am I missing something that would make this approach either undesirable or impossible?

    Thanks

  8. #8
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,630
    Thanks
    13
    Thanked 1,592 Times in 1,520 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Create QMainWindow from different thread

    Take a look at ActiveQt which, for ActiveX controls on Windows, manages creating a QApplication (if one does not already exist) hooked into the non-Qt event loop.

    https://qt.gitorious.org/qt/qtactive...serverbase.cpp

  9. #9
    Join Date
    Dec 2009
    Location
    New Orleans, Louisiana
    Posts
    791
    Thanks
    13
    Thanked 153 Times in 150 Posts
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: Create QMainWindow from different thread

    Thanks ChrisW. I'll go through that code tonight in more detail. A quick read looks like it creates a QApplication if qApp is null and then does a qApp->processEvents(), but a quick read didn't show that it does an exec().

    It also has the luxury or burden (depending how you look at it) that it can be in-process or out-of-process, so my guess it handles those cases differently.

    Thanks for the pointer though.

Similar Threads

  1. Replies: 2
    Last Post: 17th August 2013, 15:43
  2. QMainWindow: create onStartup-like function [SOLVED]
    By thomaspu in forum Qt Programming
    Replies: 3
    Last Post: 11th October 2012, 14:42
  3. Create QMainWindow in runtime
    By qt_developer in forum Newbie
    Replies: 2
    Last Post: 25th June 2012, 19:22
  4. Replies: 6
    Last Post: 22nd December 2011, 21:03
  5. Replies: 1
    Last Post: 23rd December 2010, 23:32

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.