Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Connecting Signals in dynamically created objects to Slots in MainWindow



  • I'm trying to keep all my GUI code inside MainWindow, in order to follow best practice.

    I have a class A (instantiated in MainWindow) which holds dynamically created instances of class B inside a QList.

    The instances of class B need to emit a signal when their data changes. A slot in MainWindow needs to receive these signals.

    The obvious solution is to either store a pointer to MainWindow in a global variable, or pass a pointer to Mainwindow to class A, and then the instances of class B, and do the Connect() inside class B. However, I've been told it is bad practice to expose MainWindow to other classes. Also don't like the idea of passing MainWindow to class A just so it can be passed to class B.

    What's the best way to approach this problem?


  • Qt Champions 2019

    Let class B emit a signal, connect this signal in the MainWindow.



  • @EaccB said in Connecting Signals in dynamically created objects to Slots in MainWindow:

    The instances of class B need to emit a signal when their data changes. A slot in MainWindow needs to receive these signals.

    and do the Connect() inside class B.

    Why would you want to do the connect() inside class B? B emit()s, it's not its job to connect to any slot: in fact, part of the point of signals/slots is precisely that the emitter doesn't know about any listeners, so it can't do connects. Do the connect()s in the caller creating instances of B, not in B. So in A here. Or back in MainWindow if you can, depending on its interface with class A instances.



  • @JonB

    How would I connect the signal in class B to MainWindow, in class A?
    Or are you saying I should connect the signal in B to a slot in A, which emits a signal which is received by a slot in MainWindow? If so, isn't this indirect "chaining" rather unwieldy?



  • @EaccB
    I assume MainWindow creates a class A instance, I don't know whether one or many. Class A creates the Bs. Can the MainWindow hook the slots after it has created the A? One thing for sure is that class B should not be doing the connects.



  • @JonB

    MainWindow creates 1 instance of class A. Class A creates multiple instances of class B.



  • @EaccB

    MainWindow:
        a = new A()
        foreach (b in a.listOfBs)
            connect(b, signal, this, slot)
    

    ?



  • @JonB

    Right, so basically returning the instances of B back to MainWindow?

    As B is instantiated dynamically, should I emit a Signal from A to MainWindow, when a new instance of B is created, so the connection can be made?



  • @EaccB
    So you're saying that as your program runs new instances of B will be created periodically, and the main window has a slot which needs to be connected to a signal from B, right?

    Doubtless use cases vary, but, yes, why not have a helper method for creating a new B which emits a signal. Mainwindow has a slot for that, and connects the freshly created B to its slot. The good thing is that when the hierarchy becomes deeper and you have A creating B creating C creating D, you can still use this principle to connect D's signal to the main window without passing the main window down all over the place.

    Unless a Qt expert says otherwise...


  • Lifetime Qt Champion

    Hi
    Just as a note.
    It's also possible to do signal to signal connects.
    So if MainWindow just needs to know data has changed to reload something
    then you could also

    Define new Signal in class A
    void DataChangedForB

    and internally when you create the B's, connect B's
    signal datachanged to A::DataChangedForB signal

    And then in MainWindow, simply connect Mains slot to
    the new A::DataChangedForB signal

    However, if you are using sender() to access the B' instance, this wont work.