Results 1 to 11 of 11

Thread: Refresh application GUI after running external application

  1. #1
    Join Date
    Jun 2015
    Posts
    7
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Refresh application GUI after running external application

    Hello,

    I'm looking for some advice on how to refresh/redraw my main application after running an external application.

    Currently I'm doing the following:

    Qt Code:
    1. QProcess systemCall;
    2. systemCall.start( externalAppPath, externalAppArgs );
    3. systemCall.waitForFinished( -1 ); //wait indefinitely for process to finish
    4. systemCall.close();
    5.  
    6. QWidget *qwParent = this;
    7. while( (qwParent) )
    8. {
    9. qDebug() << "repainting parent :" << qwParent;
    10. qwParent->repaint();
    11. qwParent = qwParent->parentWidget();
    12. qDebug() << "next parent :" << qwParent;
    13. }
    To copy to clipboard, switch view to plain text mode 

    As one of the options in my main application I have to launch our external application and wait for it to finish.
    On exiting the external application and returning to my main app I need to repaint all parent widgets using the above while loop.

    My question is - is there a better way of achieving this?

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Refresh application GUI after running external application

    Well, it is usually very bad to block event processing of a UI application.
    Do you have a specific requirement for that?

    Cheers,
    _

  3. #3
    Join Date
    Oct 2009
    Posts
    483
    Thanked 97 Times in 94 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Refresh application GUI after running external application

    Why do you think you need to explicitly redraw all widgets? Qt handles this as long as you let control return to the event loop. Your current code, which blocks the UI thread until the external process has finished executing, is inelegant because it prevents the user from interacting with your application, and the widgets are not updated. However, if you return to the event loop after the external process has finished executing, the widgets should be updated automatically.

    Now, if you want the UI to remain responsive while the external process is running, you need an event loop to be running. Instead of calling QProcess::waitForFinished(), you could connect QProcess::finished() to a slot, then start the process and return to the event loop. Your slot will be executed after the external process has finished executing.

  4. #4
    Join Date
    Jun 2015
    Posts
    7
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Refresh application GUI after running external application

    Quote Originally Posted by anda_skoa View Post
    Well, it is usually very bad to block event processing of a UI application.
    Do you have a specific requirement for that?

    Cheers,
    _
    Quote Originally Posted by yeye_olive View Post
    Why do you think you need to explicitly redraw all widgets? Qt handles this as long as you let control return to the event loop. Your current code, which blocks the UI thread until the external process has finished executing, is inelegant because it prevents the user from interacting with your application, and the widgets are not updated. However, if you return to the event loop after the external process has finished executing, the widgets should be updated automatically.

    Now, if you want the UI to remain responsive while the external process is running, you need an event loop to be running. Instead of calling QProcess::waitForFinished(), you could connect QProcess::finished() to a slot, then start the process and return to the event loop. Your slot will be executed after the external process has finished executing.
    See attached image when I launch my external application without blocking the main app. I get the following:
    Attachment 11255
    alternative link to image
    With the above code I am trying to prevent this occurring.

    Also, when using the external application, the user should not be interacting with the main application so I felt that waiting for the external application to finish was the best option.

    I am open to any/all suggestions on how to achieve this in a better way.
    Thanks
    Last edited by evanol; 6th July 2015 at 12:17.

  5. #5
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Refresh application GUI after running external application

    As yeye_olive wrote, you don't need any special widget updating, just return from the slot.

    I would still not artificially freeze the application.

    The option that is closest to your current code is to use a QEventLoop instance and connect the process' finished() signal to the lop's quit() slot.
    Then you run exec() with the flag to exclude user input.

    Additionally, as a visual clue for the user, I would disable the UI before running the nested loop and re-enable it after exec() returns.

    Another option is to use a modal dialog.

    Cheers,
    _

  6. #6
    Join Date
    Oct 2009
    Posts
    483
    Thanked 97 Times in 94 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Refresh application GUI after running external application

    I cannot download the attachment in your last post. I get an error 'Invalid Attachment specified' when I try to do so.

    Globally preventing user interaction is frowned upon, because you do not even let the user close the application. If you want to prevent interaction with specific widgets, call QWidget::setEnabled(false).

    Nevertheless, if you insist on preventing user interaction, you could still run a local QEventLoop with the QEventLoop::ExcludeUserInputEvents flag.

  7. #7
    Join Date
    Jun 2015
    Posts
    7
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Refresh application GUI after running external application

    Quote Originally Posted by anda_skoa View Post
    As yeye_olive wrote, you don't need any special widget updating, just return from the slot.

    I would still not artificially freeze the application.

    The option that is closest to your current code is to use a QEventLoop instance and connect the process' finished() signal to the lop's quit() slot.
    Then you run exec() with the flag to exclude user input.

    Additionally, as a visual clue for the user, I would disable the UI before running the nested loop and re-enable it after exec() returns.

    Another option is to use a modal dialog.

    Cheers,
    _
    Quote Originally Posted by yeye_olive View Post
    I cannot download the attachment in your last post. I get an error 'Invalid Attachment specified' when I try to do so.

    Globally preventing user interaction is frowned upon, because you do not even let the user close the application. If you want to prevent interaction with specific widgets, call QWidget::setEnabled(false).

    Nevertheless, if you insist on preventing user interaction, you could still run a local QEventLoop with the QEventLoop::ExcludeUserInputEvents flag.
    @ yeye_olive - i've added an alternate link to the image

    Thank you both for your feedback.
    The main application is running on an embedded linux device and as such the user can never close the main application window.
    The device turns-on & launches the main application.
    The application (& device) is then shutdown when a user activity timeout occurs or a hardware button is pressed.

    I will look into both of your suggestions - any code samples / examples / links that may be helpful would be appreciated
    Last edited by evanol; 6th July 2015 at 12:15.

  8. #8
    Join Date
    Jun 2015
    Posts
    7
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Refresh application GUI after running external application

    @ anda_skoa - i've taken the idea of using QDialog to accomplish this, which negates the need to manually update parent widgets.

    Any comments/feedback welcome...

    Qt Code:
    1. #include "externalAppdialog.h"
    2. #include "ui_externalAppdialog.h"
    3.  
    4. externalAppDialog::externalAppDialog(QWidget *parent) :
    5. QDialog(parent),
    6. ui(new Ui::externalAppDialog)
    7. {
    8. ui->setupUi(this);
    9. this->setWindowFlags( Qt::FramelessWindowHint );
    10.  
    11. connect( this, SIGNAL( finished( int ) ), this, SLOT( deleteLater() ) );
    12. this->showFullScreen();
    13.  
    14. activityTicker = new QTimer( this );
    15. connect( activityTicker, SIGNAL( timeout() ), this, SLOT( keepMainAppAlive() ) );
    16. activityTicker->setInterval( (30 * 1000) ); //every 30s;
    17.  
    18. systemCall = new QProcess( this );
    19. connect( systemCall, SIGNAL( finished(int) ), this, SLOT( accept() ) );
    20. connect( systemCall, SIGNAL( finished(int) ), activityTicker, SLOT( stop() ) );
    21.  
    22. QTimer::singleShot( 0, this, SLOT( launchexternalAppApp() ) );
    23. }
    24.  
    25. externalAppDialog::~externalAppDialog()
    26. {
    27. delete ui;
    28. }
    29.  
    30. void externalAppDialog::launchexternalAppApp( void )
    31. {
    32. systemCall->start( QString( "%1/%2" )
    33. .arg( "externalAppPath" )
    34. .arg( "externalApp" ),
    35. << "-qws" );
    36. activityTicker->start();
    37. }
    38.  
    39. void externalAppDialog::keepMainAppAlive( void )
    40. {
    41. qApp->postEvent( this, new QEvent( QEvent::MouseMove ) );
    42. }
    To copy to clipboard, switch view to plain text mode 

  9. #9
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Refresh application GUI after running external application

    Why post a fake mouse event to the dialog?

    You can also replace the connect in line 11 with setting the Qt::WA_DeleteOnClose attribute.

    Cheers,
    _

  10. #10
    Join Date
    Jun 2015
    Posts
    7
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Refresh application GUI after running external application

    Why post a fake mouse event to the dialog?
    The main application has a user inactivity timer whereby the device (& application) is shut-down after a period of time. While running the external application, this inactivity timer needs to be serviced(restarted) to prevent this occurring - is there an alternate way of achieving this?

    You can also replace the connect in line 11 with setting the Qt::WA_DeleteOnClose attribute.
    Thanks, i've adjusted my code to use the Qt::WA_DeleteOnClose attribute.
    Is there an advantage to using the attribute vs the connect I used previously?

  11. #11
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Refresh application GUI after running external application

    Quote Originally Posted by evanol View Post
    The main application has a user inactivity timer whereby the device (& application) is shut-down after a period of time.
    Ah

    Quote Originally Posted by evanol View Post
    While running the external application, this inactivity timer needs to be serviced(restarted) to prevent this occurring - is there an alternate way of achieving this?
    You could just emit a signal from the dialog and connect it to whatever slot triggers the reset of your inactivity watchdog.

    Quote Originally Posted by evanol View Post
    Thanks, i've adjusted my code to use the Qt::WA_DeleteOnClose attribute.
    Is there an advantage to using the attribute vs the connect I used previously?
    They are both pretty equivalent. The attribute has the advantage that it always triggers, no matter if the finished() signal is being emitted or not.
    E.g. if the dialog is exited via a code path that does not include the respective emit or when the widget is not a dialog (i.e. works for all kinds of windows)

    Cheers,
    _

Similar Threads

  1. Closing an external application with qt
    By Capton in forum Newbie
    Replies: 1
    Last Post: 19th June 2013, 23:45
  2. embed qt exe in external application
    By rattanas in forum Newbie
    Replies: 0
    Last Post: 5th May 2013, 07:59
  3. Replies: 4
    Last Post: 19th November 2012, 14:35
  4. How to control an external application?
    By lixo1 in forum Qt Programming
    Replies: 4
    Last Post: 25th September 2009, 21:29
  5. Replies: 12
    Last Post: 29th February 2008, 13:35

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.