Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to connect backend classes with the GUI properly?
Forum Updated to NodeBB v4.3 + New Features

How to connect backend classes with the GUI properly?

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 3 Posters 1.3k Views 1 Watching
  • 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.
  • M Offline
    M Offline
    mayfairstrange
    wrote on 20 May 2022, 09:34 last edited by
    #1

    Hello, I am new to Qt from this year, and am making a board game using Qt 6.

    There is no specific code example I can show to make my problem clear, so please bare with me.

    My backend classes have already been created with pure C++, that I now added to Qt to create a GUI that interacts with them. My idea is to use my Game class as a public interface, which also has constant references to some helper classes that can be called from within the GUI.

    In general, this approach ensures information hiding as the GUI can't access anything non-const in my deeper backend classes. However, when I want to connect signals with slots, I need a pure pointer to the class that holds the signals/slots. So when adding signals to the most logical backend class, I would need a pointer to this class in the GUI, to make the connect. This would however destroy the information hiding principle, as now every method can be called from the GUI.

    Is there anything I am doing wrong here? What is a possible solution that doesn't violate GRASP too much?

    An example:
    My game has a private member that manages 'rounds' in the board game. Whenever a round is over, I want to send a signal from the RoundManager to the MainWindow (this class holds my Game pointer and initializes it).

    A connect is now needed, so the only solution I can come up with is this:

    • Add a getter in Game that returns a pure pointer to the private RoundManager member (not const anymore).

    • Call the getter in the GUI to pass it to the first parameter of the connect.

    What I thought about:

    • Have all signals in the public Game class, as I have a pointer to this class in the GUI. (but then where to emit them?)
      This however, violates GRASP's information expert (Game shouldn't include all signals that are specific to certain classes)

    Thanks in advance for any advice or help.

    J 1 Reply Last reply 20 May 2022, 09:50
    0
    • M mayfairstrange
      20 May 2022, 09:34

      Hello, I am new to Qt from this year, and am making a board game using Qt 6.

      There is no specific code example I can show to make my problem clear, so please bare with me.

      My backend classes have already been created with pure C++, that I now added to Qt to create a GUI that interacts with them. My idea is to use my Game class as a public interface, which also has constant references to some helper classes that can be called from within the GUI.

      In general, this approach ensures information hiding as the GUI can't access anything non-const in my deeper backend classes. However, when I want to connect signals with slots, I need a pure pointer to the class that holds the signals/slots. So when adding signals to the most logical backend class, I would need a pointer to this class in the GUI, to make the connect. This would however destroy the information hiding principle, as now every method can be called from the GUI.

      Is there anything I am doing wrong here? What is a possible solution that doesn't violate GRASP too much?

      An example:
      My game has a private member that manages 'rounds' in the board game. Whenever a round is over, I want to send a signal from the RoundManager to the MainWindow (this class holds my Game pointer and initializes it).

      A connect is now needed, so the only solution I can come up with is this:

      • Add a getter in Game that returns a pure pointer to the private RoundManager member (not const anymore).

      • Call the getter in the GUI to pass it to the first parameter of the connect.

      What I thought about:

      • Have all signals in the public Game class, as I have a pointer to this class in the GUI. (but then where to emit them?)
        This however, violates GRASP's information expert (Game shouldn't include all signals that are specific to certain classes)

      Thanks in advance for any advice or help.

      J Offline
      J Offline
      JonB
      wrote on 20 May 2022, 09:50 last edited by JonB
      #2

      @mayfairstrange said in How to connect backend classes with the GUI properly?:

      This would however destroy the information hiding principle, as now every method can be called from the GUI.

      ? Assuming you make your Game class(es) derive from QObject and have Q_OBJECT macro in it/them, so that they can emit signals, it is only those signals which must be public. You do not have to expose any other methods in them to the UI.

      At a pinch you could probably make it so you do not have to make your Game class(es) "derive from QObject and have Q_OBJECT macro" by defining a separate class with that as a "wrapper" for signal emits which the backend class(es) call instead of emit directly, with some judicious method definitions/parameter passing. And use that class in the UI's connect()s. More work though.

      1 Reply Last reply
      1
      • M Offline
        M Offline
        mayfairstrange
        wrote on 20 May 2022, 11:04 last edited by mayfairstrange
        #3

        Hello, thank you for your answer. The classes contained in Game that must emit signals are derived from QObject and have the QObject macro. How do I connect those signals in the UI?

        Here is a template of my example:

        // RoundManager.h
        class RoundManager : public QObject{
           Q_OBJECT
        signals:
              void roundOver();
        }
        //Game.h
        class Game : public QObject {
          Q_OBJECT
        public:
          inline RoundManager* roundManagerPtr() {return m_roundManager; } // Exposes all methods in roundmanager
        private:
          RoundManager* m_roundManager;
        }
        // MainWindow.h
        class MainWindow : public QMainWindow {
          Q_OBJECT
        public slots:
            void handleRoundOver();
        private:
           Game* m_game;
        }
        // MainWindow constructor
        connect(m_game->roundManagerPtr(), &RoundManager::roundOver, this, &MainWindow::handleRoundOver);
        

        How would I connect this signal alone without getting a pointer to the RoundManager class?

        M 1 Reply Last reply 20 May 2022, 11:29
        0
        • M mayfairstrange
          20 May 2022, 11:04

          Hello, thank you for your answer. The classes contained in Game that must emit signals are derived from QObject and have the QObject macro. How do I connect those signals in the UI?

          Here is a template of my example:

          // RoundManager.h
          class RoundManager : public QObject{
             Q_OBJECT
          signals:
                void roundOver();
          }
          //Game.h
          class Game : public QObject {
            Q_OBJECT
          public:
            inline RoundManager* roundManagerPtr() {return m_roundManager; } // Exposes all methods in roundmanager
          private:
            RoundManager* m_roundManager;
          }
          // MainWindow.h
          class MainWindow : public QMainWindow {
            Q_OBJECT
          public slots:
              void handleRoundOver();
          private:
             Game* m_game;
          }
          // MainWindow constructor
          connect(m_game->roundManagerPtr(), &RoundManager::roundOver, this, &MainWindow::handleRoundOver);
          

          How would I connect this signal alone without getting a pointer to the RoundManager class?

          M Offline
          M Offline
          mpergand
          wrote on 20 May 2022, 11:29 last edited by mpergand
          #4

          @mayfairstrange said in How to connect backend classes with the GUI properly?:

          How would I connect this signal alone without getting a pointer to the RoundManager class?

          You can't.

          inline RoundManager* roundManagerPtr() {return m_roundManager; } // Exposes all methods in roundmanager

          Will expose only public methods.

          Now if you do not want RoundManager to be exposed outside the Game class, define the Game class as a proxy, that is an intermediate class between your app and RoundManager.

          M 1 Reply Last reply 20 May 2022, 11:44
          1
          • M mpergand
            20 May 2022, 11:29

            @mayfairstrange said in How to connect backend classes with the GUI properly?:

            How would I connect this signal alone without getting a pointer to the RoundManager class?

            You can't.

            inline RoundManager* roundManagerPtr() {return m_roundManager; } // Exposes all methods in roundmanager

            Will expose only public methods.

            Now if you do not want RoundManager to be exposed outside the Game class, define the Game class as a proxy, that is an intermediate class between your app and RoundManager.

            M Offline
            M Offline
            mayfairstrange
            wrote on 20 May 2022, 11:44 last edited by
            #5

            @mpergand Thank you, a definite answer is what I wanted to see. I will have to solve it that way then indeed.

            1 Reply Last reply
            0

            1/5

            20 May 2022, 09:34

            • Login

            • Login or register to search.
            1 out of 5
            • First post
              1/5
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved