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. Remove widget from QStackedWidget and bring it back

Remove widget from QStackedWidget and bring it back

Scheduled Pinned Locked Moved Solved General and Desktop
new windowshow widgetqstackedwidget
6 Posts 2 Posters 606 Views
  • 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
    SergeyK12
    wrote on 13 Aug 2024, 20:41 last edited by SergeyK12
    #1

    Hi!
    Im trying to show widget from QStackedWidget in separate window and bring it back after close. (by seParent(nullptr) and show)

    When widget is added back and signal to show this widget is emitted, widget is unseen.
    But clicking on button manually with connected same slot i can see widget

    // show widget in QStackedWidget (_stacked)
            connect(action, &QAction::triggered, [this, plugin](){
                _stacked->setCurrentWidget(plugin);
                plugin->show();
            });
    
    // show widget (plugin) in separate window
            connect(asWindow, &QAction::triggered, [this, action, plugin](){
                plugin->setParent(nullptr);
                plugin->show();
                action->setVisible(false);
            });
    
    // connect with custom signal widget is closed and bring back into stacked
            connect(plugin, &IModuleView::objectWindowIsClosed, [this, action, toolButton](QWidget* w){
                _stacked->addWidget(w);
                action->setVisible(true);
                action->trigger();
            });
    

    Trying to do repaint and updates show that widget is there but is instantly hide.

    I also try to clone widget and show it in window when hiding/ showing widget form QStackedWidget (it is worked, but im not sure is simple to clone complex widget)

    P 1 Reply Last reply 14 Aug 2024, 04:14
    0
    • S SergeyK12
      13 Aug 2024, 20:41

      Hi!
      Im trying to show widget from QStackedWidget in separate window and bring it back after close. (by seParent(nullptr) and show)

      When widget is added back and signal to show this widget is emitted, widget is unseen.
      But clicking on button manually with connected same slot i can see widget

      // show widget in QStackedWidget (_stacked)
              connect(action, &QAction::triggered, [this, plugin](){
                  _stacked->setCurrentWidget(plugin);
                  plugin->show();
              });
      
      // show widget (plugin) in separate window
              connect(asWindow, &QAction::triggered, [this, action, plugin](){
                  plugin->setParent(nullptr);
                  plugin->show();
                  action->setVisible(false);
              });
      
      // connect with custom signal widget is closed and bring back into stacked
              connect(plugin, &IModuleView::objectWindowIsClosed, [this, action, toolButton](QWidget* w){
                  _stacked->addWidget(w);
                  action->setVisible(true);
                  action->trigger();
              });
      

      Trying to do repaint and updates show that widget is there but is instantly hide.

      I also try to clone widget and show it in window when hiding/ showing widget form QStackedWidget (it is worked, but im not sure is simple to clone complex widget)

      P Offline
      P Offline
      Pl45m4
      wrote on 14 Aug 2024, 04:14 last edited by Pl45m4
      #2

      @SergeyK12 said in Remove widget from QStackedWidget and bring it back:

      Trying to do repaint and updates show that widget is there but is instantly hide.

      You have probably an issue with the lifetime of your widget.
      &IModuleView::objectWindowIsClosed this signal name sounds like you emit the signal when you close the plugin...
      Adding the plugin back to the stackedWidget (by triggering the action) might not work then.

      This simple example works for me:

      StackedWidget.gif

      #include "widget.h"
      #include "ui_widget.h"
      
      #include <QPushButton>
      #include <QDebug>
      
      
      Widget::Widget(QWidget *parent)
          : QWidget(parent)
          , ui(new Ui::Widget)
      {
          ui->setupUi(this);
          
          QPushButton *pb = new QPushButton("Widget");
          ui->stackedWidget->addWidget(pb);
          ui->stackedWidget->setCurrentWidget(pb);
          
          // pushbutton in UI only to toggle the other button from free floating to be in stackedWidget
          connect(ui->pushButton, &QPushButton::clicked, this, [=](){
              
              if (ui->stackedWidget->currentWidget() == pb) {
                  ui->stackedWidget->removeWidget(pb);
                  pb->setParent(nullptr);
                  qDebug() << "Show standalone";
                  pb->show();
              }
              else {
                  ui->stackedWidget->addWidget(pb);
                  ui->stackedWidget->setCurrentWidget(pb);
                  qDebug() << "Add to stackedWidget";
              }
          });
      }
      
      Widget::~Widget()
      {
          delete ui;
      }
      
      }
      
      

      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

      ~E. W. Dijkstra

      S 1 Reply Last reply 14 Aug 2024, 16:56
      0
      • P Pl45m4
        14 Aug 2024, 04:14

        @SergeyK12 said in Remove widget from QStackedWidget and bring it back:

        Trying to do repaint and updates show that widget is there but is instantly hide.

        You have probably an issue with the lifetime of your widget.
        &IModuleView::objectWindowIsClosed this signal name sounds like you emit the signal when you close the plugin...
        Adding the plugin back to the stackedWidget (by triggering the action) might not work then.

        This simple example works for me:

        StackedWidget.gif

        #include "widget.h"
        #include "ui_widget.h"
        
        #include <QPushButton>
        #include <QDebug>
        
        
        Widget::Widget(QWidget *parent)
            : QWidget(parent)
            , ui(new Ui::Widget)
        {
            ui->setupUi(this);
            
            QPushButton *pb = new QPushButton("Widget");
            ui->stackedWidget->addWidget(pb);
            ui->stackedWidget->setCurrentWidget(pb);
            
            // pushbutton in UI only to toggle the other button from free floating to be in stackedWidget
            connect(ui->pushButton, &QPushButton::clicked, this, [=](){
                
                if (ui->stackedWidget->currentWidget() == pb) {
                    ui->stackedWidget->removeWidget(pb);
                    pb->setParent(nullptr);
                    qDebug() << "Show standalone";
                    pb->show();
                }
                else {
                    ui->stackedWidget->addWidget(pb);
                    ui->stackedWidget->setCurrentWidget(pb);
                    qDebug() << "Add to stackedWidget";
                }
            });
        }
        
        Widget::~Widget()
        {
            delete ui;
        }
        
        }
        
        
        S Offline
        S Offline
        SergeyK12
        wrote on 14 Aug 2024, 16:56 last edited by SergeyK12
        #3

        When i closed widget with cross i suppose that following code will be executed (because i override event)

        protected:
            void closeEvent(QCloseEvent *event) override
            {
                emit objectWindowIsClosed(this);
            }
        

        But not only this event happened?

        Im trying to connect to this signal to automatically bring widget into _stacked (and emit defaultAction of button), but its only worked when i manually press on button (as in your example).

        Could it be a problem with focus on mainwindow (when we click manually its somehow activated )?

        Im even seen a layout widget slightly moved when widget back, but its not seen.

        P 1 Reply Last reply 14 Aug 2024, 18:18
        0
        • S SergeyK12
          14 Aug 2024, 16:56

          When i closed widget with cross i suppose that following code will be executed (because i override event)

          protected:
              void closeEvent(QCloseEvent *event) override
              {
                  emit objectWindowIsClosed(this);
              }
          

          But not only this event happened?

          Im trying to connect to this signal to automatically bring widget into _stacked (and emit defaultAction of button), but its only worked when i manually press on button (as in your example).

          Could it be a problem with focus on mainwindow (when we click manually its somehow activated )?

          Im even seen a layout widget slightly moved when widget back, but its not seen.

          P Offline
          P Offline
          Pl45m4
          wrote on 14 Aug 2024, 18:18 last edited by Pl45m4
          #4

          @SergeyK12 said in Remove widget from QStackedWidget and bring it back:

          But not only this event happened?

          The closeEvent is more powerful than your signal. It will complete the process to close/hide the widget.

          Now I tried like your way.
          I used a more complex widget and emitted a signal in closeEvent.
          Afterwards I connected the signal to a lambda to add the transmitted widget pointer again.
          And it shows the same behavior as you describe... I only see the widget in my QStackedWidget when I click the button (without the signal in closeEvent).

          The explanation is in my first two sentences above.
          Even if you emit the signal to move the widget to stackedWidget, the closeEvent will finish and "close" the widget.
          And because the closeEvent finishes after the signal is emitted, you don't see the widget in stackedWidget, while everything else seems correct. Therefore you can't bring the widget back up while the closeEvent hasn't finished.

          [Edit: See both solutions below: Either delay moving and showing the widget as QStackedWidget page with a timer or ignore the closeEvent as you don't want to actually close the widget. You just want to move it somewhere else while being visible]

          @SergeyK12 said in Remove widget from QStackedWidget and bring it back:

          protected:
          void closeEvent(QCloseEvent *event) override
          {
          emit objectWindowIsClosed(this);
          }

          This will fix it:

          protected:
              void closeEvent(QCloseEvent *event) override
              {
                  // add some bool here to check condition if you want to move to stackedWidget
                  // or really close the widget
                  if ( moveToStackedWidget ) { 
                     emit objectWindowIsClosed(this);
                     event->ignore();
                  } 
                  event->accept();
              }
          

          Edit:

          Another solution that will work, but might be a little "hacky":
          Detach the move "process" (adding the plugin to stackedWidget) with a QTimer::singleShot lambda.

              connect(plugin, &IModuleView::objectWindowIsClosed, this, [=](QWidget *w) {
                  
                  // this:
                  QTimer::singleShot(0, this, [=]() {
                      stackedWidget->addWidget(w);
                      stackedWidget->setCurrentWidget(w); // or trigger your QAction here
                  });
          
                  // instead of:
                  // stackedWidget->addWidget(w);
                  // stackedWidget->setCurrentWidget(w);
              });
          

          Then you don't need to ignore the event and can leave the emit objectWindowIsClosed(this); as it is.

          For the second idea, I don't know how bad it really is or if this is actually the better way. However it worked for me.

          Maybe others can tell :)

          Cheers :))


          If debugging is the process of removing software bugs, then programming must be the process of putting them in.

          ~E. W. Dijkstra

          S 1 Reply Last reply 14 Aug 2024, 20:48
          0
          • P Pl45m4
            14 Aug 2024, 18:18

            @SergeyK12 said in Remove widget from QStackedWidget and bring it back:

            But not only this event happened?

            The closeEvent is more powerful than your signal. It will complete the process to close/hide the widget.

            Now I tried like your way.
            I used a more complex widget and emitted a signal in closeEvent.
            Afterwards I connected the signal to a lambda to add the transmitted widget pointer again.
            And it shows the same behavior as you describe... I only see the widget in my QStackedWidget when I click the button (without the signal in closeEvent).

            The explanation is in my first two sentences above.
            Even if you emit the signal to move the widget to stackedWidget, the closeEvent will finish and "close" the widget.
            And because the closeEvent finishes after the signal is emitted, you don't see the widget in stackedWidget, while everything else seems correct. Therefore you can't bring the widget back up while the closeEvent hasn't finished.

            [Edit: See both solutions below: Either delay moving and showing the widget as QStackedWidget page with a timer or ignore the closeEvent as you don't want to actually close the widget. You just want to move it somewhere else while being visible]

            @SergeyK12 said in Remove widget from QStackedWidget and bring it back:

            protected:
            void closeEvent(QCloseEvent *event) override
            {
            emit objectWindowIsClosed(this);
            }

            This will fix it:

            protected:
                void closeEvent(QCloseEvent *event) override
                {
                    // add some bool here to check condition if you want to move to stackedWidget
                    // or really close the widget
                    if ( moveToStackedWidget ) { 
                       emit objectWindowIsClosed(this);
                       event->ignore();
                    } 
                    event->accept();
                }
            

            Edit:

            Another solution that will work, but might be a little "hacky":
            Detach the move "process" (adding the plugin to stackedWidget) with a QTimer::singleShot lambda.

                connect(plugin, &IModuleView::objectWindowIsClosed, this, [=](QWidget *w) {
                    
                    // this:
                    QTimer::singleShot(0, this, [=]() {
                        stackedWidget->addWidget(w);
                        stackedWidget->setCurrentWidget(w); // or trigger your QAction here
                    });
            
                    // instead of:
                    // stackedWidget->addWidget(w);
                    // stackedWidget->setCurrentWidget(w);
                });
            

            Then you don't need to ignore the event and can leave the emit objectWindowIsClosed(this); as it is.

            For the second idea, I don't know how bad it really is or if this is actually the better way. However it worked for me.

            Maybe others can tell :)

            Cheers :))

            S Offline
            S Offline
            SergeyK12
            wrote on 14 Aug 2024, 20:48 last edited by
            #5

            @Pl45m4 said in Remove widget from QStackedWidget and bring it back:

            event->ignore();

            Amazing!

            Thank you very much!

            I found out very important thing about Qt!

            P 1 Reply Last reply 15 Aug 2024, 06:14
            1
            • S SergeyK12
              14 Aug 2024, 20:48

              @Pl45m4 said in Remove widget from QStackedWidget and bring it back:

              event->ignore();

              Amazing!

              Thank you very much!

              I found out very important thing about Qt!

              P Offline
              P Offline
              Pl45m4
              wrote on 15 Aug 2024, 06:14 last edited by
              #6

              @SergeyK12

              Great, so please mark your topic as solved


              If debugging is the process of removing software bugs, then programming must be the process of putting them in.

              ~E. W. Dijkstra

              1 Reply Last reply
              0
              • S SergeyK12 has marked this topic as solved on 21 Aug 2024, 16:19
              • P Pl45m4 referenced this topic on 21 Oct 2024, 04:09

              1/6

              13 Aug 2024, 20:41

              • Login

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