I have my MainWindow that open a second Window.
When I click on a button in my second window, a thread is launched and I want my thread to end when I quit my second window.
What is the signal emitted when my SecondWindow is closed ?
Thank you for your futures answers
There is no signal emitted when widgets (including QMainWindows) are closed. If a widget is set to be deleted when it is closed then you could use the following QObject signal to detect when the widget is about to be destroyed...
void destroyed(QObject *obj = Q_NULLPTR)
However this will only work if your window has the Qt::WA_DeleteOnClose flag enabled (it is not enabled by default).
Alternatively and probably more preferably you can implement the standard widget close event and emit your own signal to indicate that the window was closed:
void MainWindow::closeEvent( QCloseEvent* event )
{
emit MySignalToIndicateThatTheWindowIsClosing();
event->accept();
}
Related
I have a complex widget on the screen which is visible. By pushing a button a dialog appears but parts of the original widget is still visible. When closing the dialog I would like to refresh some data of my particular widget ... but this widget does not know anything about that dialog. Is there any event I can check for this purpose ? Or any other way to get to know when the dialogs closed ?
First I used
virtual void QWidget::showEvent( QShowEvent* event );
but it is not called when the parts of the widget is already visible.
EDIT
I'm sorry but I wasn't precise enough. When I wrote complex, I meant that I have a main window, which has a child widget which also has child widget and so on (for about file level). That lowest level child widget initiates the opening of the dialog. The other widget which needs the closing event of this dialog is also an embedded widget but somewhere else in the application. When I wrote sending the signal through many classes I meant this. In this case if want to notify my final widget I have to connect the closing signal from my source widget to several intermediate widgets which does not even interested in that signal. I also didn't want to (and can't) connect these signal/slot in the main window because of the mentioned structure. In this is there any advice ?
send the signal through many objects just for this purpose
There's no such thing as sending a signal "through" objects unless you insist on manually threading it through a bunch of them. So this doesn't make much sense unless you explain why you want to "thread" the signal through many objects ("threading" as in a string through a needle, not as in a processing thread).
A signal-slot connection has two endpoints. All you need is:
A signal at the dialog.
A slot at the supercomplex widget.
A connection set up outside of both of them. To make life simple, both the widget and the dialog could be instantiated in main(), and a connection set up before anything even appears on the screen.
The dialog signal you're looking for is simply QDialog::finished, if you have a properly designed dialog. Otherwise, use an EventSignaler of some sort to convert a QEvent::close to a signal.
The slot in the supercomplex widget should be e.g.:
Q_SLOT void refreshSomething();
Its signature/name shouldn't refer to the fact that some dialog was closed: that's coupling the API too much to the external detail of some dialog being there. The slot should get the dialog to update/refresh what you need. The reasons for invoking it are irrelevant to the widget.
Inside the widget, the slot's implementation should most likely simply call update() on one or more subwidgets, perhaps with a relevant region - if you wish to, you can have the region as an optional slot parameter.
See this question about how to forward signals or slots inside of a complex composite class that contains many objects. It's supposed to be very simple; if it's not you'll have to edit the question to indicate why it's complex for you.
At the simplest, with the most decoupled code - where the dialog knows nothing about the widget, and vice versa - as it should be, you can have:
class Dialog : public QDialog { ... };
class Widget : public QMainWindow {
Q_OBJECT
Q_SIGNAL void showDialog();
Q_SLOT void refreshSomething();
...
};
int main(int argc, char ** argv) {
QApplication app{argc, argv};
...
Widget widget;
Dialog dialog;
QObject::connect(&widget, &Widget::showDialog, &dialog, &QWidget::show);
QObject::connect(&dialog, &QDialog::finished, &widget, &Widget::refreshSomething);
widget.show();
return app.exec();
}
I'm making a c++ application in Qt, and need to programmatically close a dialog window (opened with this->exec();) via code after a certain function finishes executing.
I'm using Qt 5.6.
Thanks in advance!
Here is an example of my code, that doesn't work (Worker is the dialog Class):
void MainWindow::on_pushButton_2_clicked()
{
//When Start button clicked:
Worker worker;
worker.exec();
//worker.run(1);
worker.accept();
}
So when pushButton_2 is clicked, I want a dialog to open that gives out the current progress, and when that is done, I want it to close.
Edit:
Now you posted more code....
worker.exec();
worker.accept(); // or worker.close();
exec() starts QDialog events processing loop and will return only when completed (after accept(), reject() or done(int) is called). So worker.accept() will not be reached (you should see that if using your debugger). It must be called by worker itself after a user action (button click by instance).
What you meant to do is:
worker.show();
QThread::sleep(2); // wait for 2 seconds
worker.accept();
Then, worker.accept() will be executed at some point. Dialog is shown, but it's modal.
Old post (before edit):
You can call accept() to do as if user clicked OK or reject() to do as if user clicked Cancel.
Note that those are slots, so you can fire them by connecting a signal to them (signal to be emitted when you function finishes executing for instance).
Example:
void MyDialog::doSomethingAndClose()
{
// do your stuff here
accept(); // will close the dialog
}
or:
void MyDialog::doSomethingAndClose()
{
// do your stuff here
emit weAreDone();
}
If you earlier connected (in MyDialog constructor for instance):
connect( this, SIGNAL(weAreDone()), this, SLOT(accept()) );
Just connect your custom signal with QDialog::done(int) and emit signal after your function finishes executing.
As I've just learned, the issue is caused by the gui not updating automatically.
Here is a link to a SO question that fixes this issue.
I have a program that opens another window and i want the old window to close. Is there some function or something that would close the window through the code but keep the other window running?
this->close();
or
close();
Ref: http://doc.qt.digia.com/4.7/qwidget.html#close
void Dialog::on_Close_clicked() // Condition for Main thread program stopping
Running Thread->closethread = true;
this->close();
void Dialog::on_Stop_clicked() // Condition For Stop Button for your particular task
{
this->close();
}
MyWidget *newform = new MyWidget;
newform->show();
this->hide();
Use signal and slot mechanism.
Whenever you want to close that window or screen emit a signal and connect this signal to the close slot of that window. This should work fine.
When you get get a mouse signal from a model into your slot, the argument passed is a QModelIndex.
QModelIndex does not tell you what button is pressed. So, we can resort to QApplication::mouseButtons. But QApplication::mouseButtons is the current button press, not when model experienced the click.
My thought experiment is saying that, after the right-button is pressed, the underlying view sends the signal to my widget, but just before my widget's slot received the signal, a spurious left-click occurred. So calling QApplication::mouseButtons on receipt of QModelIndex would wrongly associate the row being click with the left mouse button rather than the right button. How possible is this scenario?
When you look at Qt and even QML, it takes a lot of code acrobatics to achieve proper mouse button info on receipt of a QModelIndex. Is it a policy that nokia is striving to promote mouse button agnosticism?
I don't think this is a very possible scenario but it may happen.
A "simple" way to be sure about which button was clicked is to subclass QTableView (or the view you are using and reimplement the mouseReleaseEvent.
void mouseReleaseEvent(QMouseEvent * event)
{
// store the button that was clicked
mButton = event->button();
// Now call the parent's event
QTableView::mouseReleaseEvent(event);
}
By default the mouseReleaseEvent emits the clicked signal if an item of the view is pressed
If a user presses the mouse inside your widget and then drags the
mouse to another location before releasing the mouse button, your
widget receives the release event. The function will emit the
clicked() signal if an item was being pressed.
The trick is to catch the clicked signal in your derived class and emit a new signal which except the model index will contain the button as well.
// Define your new signal in the header
signals:
void clicked(QModelIndex, Qt::MouseButton);
// and a slot that will emit it
private slots:
void clickedSlot(QModelIndex);
// In the constructor of your derived class connect the default clicked with a slot
connect(this, SIGNAL(clicked(QModelIndex), this, SLOT(clickedSlot(QModelIndex)));
// Now the slot just emits the new clicked signal with the button that was pressed
void clickedSlot(QModelIndex i)
{
emit clicked(i, mButton);
}
You can do something similar with the mousePressEvent if you need the pressed signal as well.
I have a QSystemTrayIcon subclass. Inside it, I have:
quitAction = new QAction(tr("&Quit"), m_parent);
connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
CloseEvent doesn't work here. How can I catch this quit event? I want to save data before closing.
You should connect your cleanup/save code to the QCoreApplication::aboutToQuit() signal.
This signal is emitted when the application is about to quit the main event loop, e.g. when the event loop level drops to zero. This may happen either after a call to quit() from inside the application or when the users shuts down the entire desktop session.