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. Launcher for multiple apps
Forum Updated to NodeBB v4.3 + New Features

Launcher for multiple apps

Scheduled Pinned Locked Moved Unsolved General and Desktop
8 Posts 3 Posters 668 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.
  • S Offline
    S Offline
    Spiel
    wrote on last edited by
    #1

    Hello,

    I have recently started learning how to use Qt , and for my project I need to make an application launcher window, which allows the user to start one (only one) from a number of Qt apps. A visual example of what is my final aim can be found here, the NRF Connect application. When you start it, a window listing different application pops up, and you select one of them.

    I attempted to create a QMainWindow with a few buttons, and tried to launch different windows upon clicking them. However, these windows disappear immediately. My aim is to close the main window, so the user cannot start another instance of the same app, or another app from the list.

    Here is my code. Can you please direct me to a suitable solution.

    #include "launcher.h"
    #include "ui_launcher.h"
    #include "appone.h"
    #include "apptwo.h"
    
    Launcher::Launcher(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::Launcher)
    {
        ui->setupUi(this);
    }
    
    Launcher::~Launcher()
    {
        delete ui;
    }
    
    void Launcher::on_app2Btn_clicked()
    {
        AppTwo app;
        app.show();
        //this->hide();
    }
    
    void Launcher::on_app1Btn_clicked()
    {
        AppOne app;
        app.show();
        //this->hide();
    }
    

    Thanks

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to devnet,

      Your app variables are on the stack and therefore lives as long as the method they are declared in.

      From your linked example, it looks rather like you have a QStackedWidget showing the appropriate things to do. That stacked widget seems to be controlled by an equivalent of a QListWidget.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      A 1 Reply Last reply
      1
      • A Offline
        A Offline
        Anonymous_Banned275
        wrote on last edited by
        #3

        You probably know by now that Qt is an event driven "tool".
        // stadard event application
        QApplication app(argc, argv);

        'I would recommend to

        1. Build plain standard "main" implementing the QApplication "loop" first.
        2. Refrain from using "app" name for your "child" applications

        This may not satisfy your task (straight from the box) , but I have been relatively successful using Qt "MDI" example as top menu driven "application ". For what its worth - using "MDI" example gives relatively standard "look and feel" of window ( as a concept, not OS) applications.

        1 Reply Last reply
        0
        • SGaistS SGaist

          Hi and welcome to devnet,

          Your app variables are on the stack and therefore lives as long as the method they are declared in.

          From your linked example, it looks rather like you have a QStackedWidget showing the appropriate things to do. That stacked widget seems to be controlled by an equivalent of a QListWidget.

          A Offline
          A Offline
          Anonymous_Banned275
          wrote on last edited by
          #4

          @SGaist I was typing my reply and did not see yours first.
          From my latest encounter with lack of understanding of "how to implement" any widget in code or using QDesigner - I think this "stacked widget " being compared to "tab widget" (as documented ) could be a prime example how Qt code - QStackedWidget and QtDesigner "tab widget" ARE TWO different and "not talking to each other " ways to code.

          End of off subject comment.

          SGaistS 1 Reply Last reply
          0
          • A Anonymous_Banned275

            @SGaist I was typing my reply and did not see yours first.
            From my latest encounter with lack of understanding of "how to implement" any widget in code or using QDesigner - I think this "stacked widget " being compared to "tab widget" (as documented ) could be a prime example how Qt code - QStackedWidget and QtDesigner "tab widget" ARE TWO different and "not talking to each other " ways to code.

            End of off subject comment.

            SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @AnneRanch what tab widget vs stacked widget ?
            In any case, a QTabWidget is built on top of QStackedWidget and QTabBar.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            0
            • S Offline
              S Offline
              Spiel
              wrote on last edited by
              #6

              Thank you for the input. I am now creating application instances as pointer variables upon each invocation. Here's my code, which is somewhat working, but I get the feel that it's lacking flexibility for adding new applications without having to extend it substantially.

              I'd like to hear your suggestions on how to make the application skeleton easy to extend with more apps ("tools") in the future. One thing that comes to mind is make the Launcher class have a vector of apps (or tools), which can be added dynamically. The Selector class can the send a signal containing a numeric value corresponding to the vector index of the app that needs to be launched.

              /******************************************************************************************/
              class Selector : public QMainWindow
              {
                  Q_OBJECT
              public:
                  Selector(QWidget *parent = nullptr);
                  ~Selector();
              private slots:
                  void on_pushButton_clicked();
                  void on_pushButton_2_clicked();
              private:
                  Ui::Selector *ui;
              signals:
                  void runToolA();
                  void runToolB();
              };
              
              Selector::Selector(QWidget *parent)
                  : QMainWindow(parent)
                  , ui(new Ui::Selector)
              {
                  ui->setupUi(this);
              }
              
              Selector::~Selector()
              {
                  delete ui;
              }
              
              void Selector::on_pushButton_clicked()
              {
                  emit runToolA();
              }
              
              void Selector::on_pushButton_2_clicked()
              {
                  emit runToolB();
              }
              /******************************************************************************************/
              class Launcher : public QObject
              {
                  Q_OBJECT
              public:
                  explicit Launcher(QObject *parent = nullptr);
              signals:
                  void toolLaunched();
                  void toolClosed();
              public slots:
                  void launchToolA();
                  void launchToolB();
              private:
                  ToolA *toolA = nullptr;
                  ToolB *toolB = nullptr;
              };
              
              void Launcher::launchToolA()
              {
                  toolA = new ToolA();
                  connect(toolA, &ToolA::windowClosed, this, &Launcher::toolClosed);
                  toolA->show();
                  emit toolLaunched();
              }
              
              void Launcher::launchToolB()
              {
                  toolB = new ToolB();
                  connect(toolB, &ToolB::windowClosed, this, &Launcher::toolClosed);
                  toolB->show();
                  emit toolLaunched();
              }
              /******************************************************************************************/
              class ToolA;
              }
              class ToolA : public QMainWindow
              {
                  Q_OBJECT
              public:
                  explicit ToolA(QWidget *parent = nullptr);
                  ~ToolA();
              signals:
                  void windowClosed();
              private:
                  Ui::ToolA *ui;
              
                  void closeEvent(QCloseEvent *event);
              };
              
              ToolA::ToolA(QWidget *parent) :
                  QMainWindow(parent),
                  ui(new Ui::ToolA)
              {
                  ui->setupUi(this);
                  this->setAttribute(Qt::WA_DeleteOnClose, true);     // Widget will be deleted automatically when closed
              }
              
              ToolA::~ToolA()
              {
                  delete ui;
              }
              /******************************************************************************************/
              void ToolA::closeEvent(QCloseEvent *event) {
                  emit windowClosed();
                  event->accept();
              }
              
              class ToolB : public QMainWindow
              {
                  Q_OBJECT
              public:
                  explicit ToolB(QWidget *parent = nullptr);
                  ~ToolB();
              signals:
                  void windowClosed();
              private:
                  Ui::ToolB *ui;
              
                  void closeEvent(QCloseEvent *event);
              };
              
              ToolB::ToolB(QWidget *parent) :
                  QMainWindow(parent),
                  ui(new Ui::ToolB)
              {
                  ui->setupUi(this);
                  this->setAttribute(Qt::WA_DeleteOnClose, true);
              }
              
              ToolB::~ToolB()
              {
                  delete ui;
              }
              
              void ToolB::closeEvent(QCloseEvent *event) {
                  emit windowClosed();
                  event->accept();
              }
              /******************************************************************************************/
              int main(int argc, char *argv[])
              {
                  QApplication a(argc, argv);
              
                  Selector selector;          // Window allows user to select Tool A or Tool B by pressing a button
                  Launcher launcher;          // The Launcher object creates an instance of the selected Tool application
              
                  QObject::connect(&selector, &Selector::runToolA, &launcher, &Launcher::launchToolA);
                  QObject::connect(&selector, &Selector::runToolB, &launcher, &Launcher::launchToolB);
              
                  QObject::connect(&launcher, &Launcher::toolLaunched, &selector, &Selector::hide);
                  QObject::connect(&launcher, &Launcher::toolClosed, &selector, &Selector::show);
              
                  selector.show();
              
                  return a.exec();
              }
              /******************************************************************************************/
              
              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                You indeed should refactor that so that you are independent of the number of tools. Make a base class that all tools will use as a base so you do not duplicate code uselessly.

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                1
                • S Offline
                  S Offline
                  Spiel
                  wrote on last edited by
                  #8

                  That's the way I'd like to go. Unfortunately I can't use a Tool interface, as the only commonality between tools is that they emit a windowClosed() event; that means the interface will need to inherit QObject, and if a tool inherits QMainWindow, as it most certainly will, that will lead to multiple inheritance. But I can't be certain that a tool will inherit QMainWindow, so I'd like to avoid creating an abstract base class inheriting QMainWindow.

                  With this in mind, I think the windowClosed() event should be renamed to something more generic, such as toolClosed().

                  Anyway, I think if a tool has a QMainWindow, or another widget, instead of inheriting from it, it will solve the problem with the inheritance. I'll try that and come back if I still can't figure it out.

                  Thanks for the suggestion!

                  1 Reply Last reply
                  0

                  • Login

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