Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

    Catching QML window close

    QML and Qt Quick
    5
    14
    19546
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • J
      jech last edited by

      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?

      1 Reply Last reply Reply Quote 0
      • A
        anselmolsm last edited by

        Hi!,
        Check if "QCloseEvent":http://doc.qt.nokia.com/4.7/qcloseevent.html or the QWidget's "closeEvent":http://doc.qt.nokia.com/4.7/qwidget.html#closeEvent can help you.

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

        Anselmo L. S. Melo (anselmolsm)

        1 Reply Last reply Reply Quote 0
        • J
          jech last edited by

          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.

          1 Reply Last reply Reply Quote 0
          • J
            jech last edited by

            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.

            1 Reply Last reply Reply Quote 0
            • I
              ixSci last edited by

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

              1 Reply Last reply Reply Quote 0
              • M
                mohsen last edited by

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

                1 Reply Last reply Reply Quote 0
                • J
                  jech last edited by

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

                  1 Reply Last reply Reply Quote 0
                  • I
                    ixSci last edited by

                    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?

                    1 Reply Last reply Reply Quote 0
                    • B
                      blam last edited by

                      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.

                      1 Reply Last reply Reply Quote 0
                      • M
                        mohsen last edited by

                        It's the second solution.

                        [quote author="blam" date="1294275363"]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.[/quote]

                        1 Reply Last reply Reply Quote 0
                        • J
                          jech last edited by

                          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.

                          1 Reply Last reply Reply Quote 0
                          • B
                            blam last edited by

                            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.

                            1 Reply Last reply Reply Quote 0
                            • J
                              jech last edited by

                              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:
                              @ Component.onDestruction: {
                              console.log("QML exit")
                              controller.onExit()
                              }
                              @

                              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.

                              1 Reply Last reply Reply Quote 0
                              • J
                                jech last edited by

                                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.

                                1 Reply Last reply Reply Quote 0
                                • First post
                                  Last post