Remove widget from QStackedWidget and bring it back
-
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)
-
@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:
#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; } }
-
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.
-
@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 incloseEvent
.
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 myQStackedWidget
when I click the button (without the signal incloseEvent
).The explanation is in my first two sentences above.
Even if you emit the signal to move the widget to stackedWidget, thecloseEvent
will finish and "close" the widget.
And because thecloseEvent
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 thecloseEvent
hasn't finished.[Edit: See both solutions below: Either delay moving and showing the widget as
QStackedWidget
page with a timer or ignore thecloseEvent
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 theplugin
tostackedWidget
) with aQTimer::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 :))
-
-