December 23, 2010

jech jech
Ant Farmer
131 posts

Catching QML window close

 

I need to call a function when the QML application closes. I use Python (PySide) as the application backend. But I suppose it should be the same for C++.

So how do I find out that the application closes and call a function?

13 replies

December 23, 2010

anselmolsm anselmolsm
Ant Farmer
417 posts

Hi!,
Check if QCloseEvent [doc.qt.nokia.com] or the QWidget’s closeEvent [doc.qt.nokia.com] can help you.

EDIT: supposing you’re using a wrapper to run your QML code.

 Signature 

Anselmo L. S. Melo (anselmolsm)
www.anselmolsm.org

December 23, 2010

jech jech
Ant Farmer
131 posts

It wasn’t exactly the solution, but by reading it’s documentation I discovered a “destroyed()” signal, which is emitted by rootContext when I close the window.

January 4, 2011

jech jech
Ant Farmer
131 posts

Unfortunately after some time, I noticed that this solution is very unreliable. Sometimes the signal is called but sometimes it isn’t. This causes that configuration is not saved and slave processes remain running, which is a very bad behavior.

Do you have any idea how can be reliably called a function at program close? The closeEvent is a good solution for traditional PySide programs, but I don’t see how could I use it with a QML UI.

January 4, 2011

ixSci ixSci
Lab Rat
206 posts

Maybe you should try *Component.onDestraction * at the main “window” of your application? It seems appropriate for your goal.

January 4, 2011

Mohsen Mohsen
Lab Rat
747 posts

ixSci is right. You can learn more here http://doc.qt.nokia.com/4.7-snapshot/qml-component.html

 Signature 

www.madagon.com

January 5, 2011

jech jech
Ant Farmer
131 posts

Unfortunately it also doesn’t work reliably. Sometimes the connected Python function is not called.

January 5, 2011

ixSci ixSci
Lab Rat
206 posts

I think there is no more reliable solution. What is the problem you have? Maybe you can make up some simple example of your troubles and we will try to eliminate them?

January 6, 2011

blam blam
Lab Rat
58 posts

If the QML application is loaded by a QDeclarativeView, then you could subclass QDeclarativeView and implement the closeEvent() as previously suggested.

With regards to Component.onDestruction, the component would only be destroyed until the QDeclarativeView is deleted (and not just closed). If the view should be deleted when it is closed then you could set its Qt::WA_DeleteOnClose attribute.

January 6, 2011

Mohsen Mohsen
Lab Rat
747 posts

It’s the second solution.

blam wrote:
If the QML application is loaded by a QDeclarativeView, then you could subclass QDeclarativeView and implement the closeEvent() as previously suggested.

With regards to Component.onDestruction, the component would only be destroyed until the QDeclarativeView is deleted (and not just closed). If the view should be deleted when it is closed then you could set its Qt::WA_DeleteOnClose attribute.

 Signature 

www.madagon.com

January 6, 2011

jech jech
Ant Farmer
131 posts

I’m sorry for my late reply. I tried to debug the behavior and found out that following situations happen:

1) Eveything works OK: The Component.onDestraction signal is emitted, that invokes an onExit Python function, which kills a slave process and saves configuration.

2) PySide fails: The Component.onDestraction signal is emitted, onExit function is executed, but the slave process isn’t killed and Python refuses to quit (complains about other threads still running).

3) PySide fails: The Component.onDestraction signal is emitted, but the onExit function isn’t executed. After this Python either exits without an error or crashes.

The behavior is quite random, it behaves differently on different machines. I’m afraid it’s a PySide problem (or my incorrect code), but since it happens randomly, I have no idea how could I provide a simple example.

I use some timers and a slave process running in a separate thread. Do I have to kill the threads manually on exit? I thought it should happen automatically.

January 7, 2011

blam blam
Lab Rat
58 posts

Is your QML running in another thread? If so that wouldn’t be a good idea; it has to be run in the main thread.

Otherwise, it could be that the Component.onDestruction signal is not what you need; perhaps you want to use the destroyed() signal from the QDeclarativeView (and setting Qt::WA_DeleteOnClose) or its engine.

January 7, 2011

jech jech
Ant Farmer
131 posts

The QML is running from the main thread. I will also test my application on Linux and with PySide 1.0 beta3, which was just released. If the problems remain, I’ll will analyze it more deeply and will try to find out what causes the crash.

Edit: One of the errors I’m getting is this: file:///../PyPlay.qml:23: TypeError: Result of expression ‘controller’ [undefined] is not an object. The controller object is used for calling functions (slots) in PySide. At lines 21-24 there is this code:

  1.    Component.onDestruction: {
  2.         console.log("QML exit")
  3.         controller.onExit()
  4.         }

So the problem appears when calling the onExit Python function. The first command of this function to write a debug information to console. It’s not written, so calling of the function fails completely. It seems to me that the Python part is destroyed to early. Subclassing the QDeclarativeView might be the solution my idea is right.

January 19, 2011

jech jech
Ant Farmer
131 posts

I just tried PySide 1.0 beta 3 but it behaves exactly as beta 1. So sometimes it crashes Python when i quit the application.

So I subclassed QDeclarativeView and defined a closeEvent function. This seems to be working so far.

The difference between the two approaches is that with closeEvent the application window isn’t closed before the function finishes. But with the use of different signals, the window closed but other Python threads were still running, which probably caused the crashes I was experiencing.

 
  ‹‹ Move from QML Only Application to Qt Quick Application with C++      Qt mobility 1.1.0 with Qt 4.7.0 help ››

You must log in to post a reply. Not a member yet? Register here!