c++ gtk open multiple window - c++

I'm still working on the example at this link: gtkmm statusicon quits after creation
I changed the function in this way to open the traybar different windows, but does not show anything.
void Tray::on_statusicon_popup(guint button, guint activate_time) {
printf("popup!\n");
Gtk::Window w;
w.show();
}
I tried to run every window with "Gtk::Main::run(w);" and it works, but I would like to not run a main loop for each window.

You're creating the window object on the stack, so it gets destroyed immediately after on_statusicon_popup() returns. If you want the window to outlast the function call, you'll need to create it on the heap and connect to its 'hide' signal (or similar) and delete the object from there.

Related

Qt DLL in MFC app - How to make QDialog *really* modal?

At the moment I am developing a Windows DLL with Qt 5.9.2 (MSVC 2015 compiler), which should be loaded by an existing, commercial MFC application. Upon request of this application a modal instance of QDialog should be displayed.
Since QApplication::exec() would block the entire application, I "simulate" the event loop using the following code:
void Core::createQApplicationInstance()
{
// Check, if there's already a 'QApplication' instance running (unlikely)
if (!QApplication::instance())
{
int argc = 1;
// Create a new 'QApplication' instance
m_app = new QApplication(argc, nullptr);
// Create a 'QTimer' instance to call 'processEvents' periodically:
// We can't run 'm_app->exec()' because it would block everything,
// so we'll use this 'hacky-whacky' method here
m_timer = new QTimer;
// Connect the timer's timeout to the app's 'processEvents' via a lambda
QObject::connect(
m_timer,
&QTimer::timeout,
[&]()
{
m_app->processEvents();
}
);
// Start the timer with the fixed 'message' interval
m_timer->start(kMsgInterval);
}
}
If my DLL should now display a modal dialog, it works (partially) with the following code:
{...}
case eUserIGeneral:
{
qDebug() << "<< eUserIGeneral";
QDialog w;
w.setModal(true);
w.exec();
// --> Code here is executed AFTER the dialog has been closed
}
break;
//-------------------------------------------------------------------
{...}
The code after w.exec() will actually be executed AFTER the dialog was closed (as intended). However, the main application still remains responsive and is not affected by the modality of my dialog, which Is not as I expected it to behave.
How can I make sure that inputs in the main application are locked when calling a modal DLL dialog?
Although I don't have a real answer to your question, there too much stuff wrong with your code to be properly explained in a comment. Therefore I am writing this as an answer.
QApplication::exec(): I strongly recommend revising the decision against it. If you want the window to be modal, why would it be wrong to "block the entire application" until it is closed? Note that you will not block the Qt part of the application, only the one that calls exec.
QTimer: A timer can only run inside an event loop. So the m_app->processEvents() either never executes, or you already have an event loop running. Either way, there is no use for the timer.
w.setModal(): If what this does is not correct for you, check out setWindowModality().
w.exec(): Ignores the value of setModal(). Read the documentation of setModal() and exec() to find out more.
w.exec(): Executes an event loop. If this somewhat does what you want, QApplication::exec() should work too. Just make sure to exit the main event loop when done.
w.exec(): Is not executed after the dialog was closed. It is executes while the dialog is shown. It blocks until the dialog is closed. So you will start executing it, show the dialog, close the dialog, and then return from it. Read the documentation of exec() to find out more.

QApplication does not exit when main window closes

I have a QMainWindow that is used to browse and view images with. These images are special medical images that are read using a wrapper that I wrote.
The GUI has a QListview on the left, which shows a list of thumbnails. When the user selects one of them, the QVTKWidget displays the corresponding image on the right. I use a vtkRenderWindowInteractor to manipulate the displayed image.
My main looks like the following:
#include <QApplication>
#include "GUIClassName.h" //inherits from QMainWindow
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
GUIClassName w;
w.show();
return a.exec();
}
My closeEvent looks like the following:
void GUIClassName::closeEvent(QCloseEvent* event)
{
// mainInteractor is a vtkSmartPointer<vtkRenderWindowInteractor>
if (this->_mainInteractor != NULL)
this->_mainInteractor->TerminateApp();
event->accept();
}
The issue is that when I close the QMainWindow, the application does not terminate. That is the command prompt stays open and Press any key to continue does not appear. If I Ctrl+break, then the application exits (obviously) but I get the following message:
QObject::~QObject: Timers cannot be stopped from another thread
I have noticed that if I only select one thumbnail and display it in the QVTKWidget, the program terminates just fine. But when I select one thumbnail, display it and then select another thumbnail, then the program does not terminate when I close the window.
I was wondering if anyone could tell me what I am doing wrong here. I would gladly copy/paste more code, but I am not sure which parts are relevant at the moment.
I have read the following in hopes of an answer, but so far I have been unable to solve this issue:
Qt app stays in memory even after MainWindow is closed
Qt process stays in memory after application closes
C++ application does not kill all processes on exit
Thanks
Did you stop all your threads?
I'm not familiar with VTK, but looks like someone run some code in thread and did not stop them properly.
RazrFalcon gave me a good hint. I am not an expert in Qt (yet) so I was looking for the Qthread that was being executed at all the wrong places.
The answer lies in the vtkRenderWindowInteractor class. For most vtkObjects (if I am not mistaken), calling new on the vtkSmartPointer deletes/stops the object if it already exists. However, this does not happen for vtkRenderWindowInteractor.
The solution was the following. When switching between thumbnails, I had to check for the existence of the interactor and if it was running, I would just call
this->_mainInteractor->TerminateApp();
to stop the hidden Qthread.

Qt creating new window from my mainwindow

so I have made 2 windows, and from my main window I am trying to create a new window when I click on a button
The function I have connected with the button looks like this
void MainWindow::ProfileCreation()
{
CreateProfile cProfile;
cProfile.show();
cProfile.raise();
cProfile.activateWindow();
}
But when I try to click on the button, the window open for like 0,5-1 sec and then closes down again
If i do this in my main.cpp file, where i create MainWindow, it works without problems and shows the window
What should I do to make the window keep showing?
cProfile is a local variable, I don't perfectly know QT but I guess as the variable is destroyed when ProfileCreation exits, the window automatically closes. You'll have to preserve cProfile, either as a class member, a global variable or created on the heap as a pointer.
If your second window is a dialog you can hide the first one and execute the second one.
this->hide();
dialog mainDialog;
dialog.setModal(true);
dialog.exec();

Qt MainWindow CloseEvent Mac Cmd+Q

On OS X 10.9 with Qt 5.2 and the following application code
#include "mywindow.h"
#include <QApplication>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MyWindow w();
w.show();
return a.exec(); }
where MyWindow derives from QMainWindow and overwrites the closeEvent(QCloseEvent*) method, this method is called when I close the application window (e.g. click the windows (x) close button), but it is not invoked when I close the application via the main Menu -> "Quit " or via the "CMD + Q" key shortcut.
From looking around the web and numerous question I got the impression that closing the application should invoke the closeEvent for all top level windows. Is this not the case, or is something going wrong here?
Edit: In addition to the above ways of closing the application, are there any other instances that I in general should handle that would result in QApplication::quit rather than invoking the window's close event? What about a system shutdown for example?
When handling a close event, I'm confirming that the user really wants to quit and I make sure cleanup like writing back changed settings is happening. Should I maybe move cleanup / saving settings to the destructor instead and do the confirmation query in closeEvent?
By default on the Mac, Qt will create an Apple Menu | Quit if a menubar doesn't exist with either quit or exit entry. That default created entry will call QApplication::quit() which will not trigger your MyWindow::closeEvent().
In your UI you should add a menu item named Exit (on the Mac it will be automagically renamed to Quit) and in the MyWindow class constructor you should connect that action to the close() slot (which is inherited from QWidget).
Update- To take a shot at your additional questions, no the destructor should probably only be used for deallocation of memory (releasing file locks, etc). Anything that could potentially involve user interaction (such prompting for a file location or alerting the user via a QMessageBox that something failed) will need to go in the closeEvent method. Saving window geometry (and other simple items using QSettings) should also be done via the closeEvent (though, I have seen code that saves geometry in the destructor work, there could be some edge cases where it does unexpected things).

Qt Application hangs on exit (after QDialog exec)

I'm using Qt to build a UI and I need to have a dialog window show up before the main app window, so that the user can select some files to load ans things like that.
What I've got is a fairly simple main:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
IView *view = new QtView();
view->showView();
int rc = a.exec();
std::cout << "exit" << std::endl;
return rc;
}
the QtView class is the concrete implementation of the IView interface.
It has the mainwindow instance and a QDialog instance too. int the view->showView() method this is what I've got:
void QtView::showView()
{
this->_configDialog->exec();
this->_mainAppWindow->show();
}
It works fine, the dialog opens and when the user clicks OK, exec returns and the main window appears. The problem is that when I quit the main window I get a zombie process and the app just seems to hang even though all the windows have been closes and I never get the "exit" I print out in the main just before the main returns.
I'm not sure what I'm doing wrong, but I get the same resutl even if I click on the cross to close the dialog, the main window opens up, and once closed the whole things just hangs there.
If anyone has any advice, that would be cool.
Thanks.
I Fixed my problem.
I used the accepted/rejected/finished(int) signal from the QDialog to trigger the show slot on the main app window, and display it if the dialog was accepted.
Thanks for the help anyway.
I think the possible reason for this behavior is that your configuration dialog may not have a parent widget set on it (it's a blind guess though as you haven't cited the relevant portion of the code). That's because QApplication by default would only quit when all the windows with no parent are closed. And the thing is, a dialog is not a window, technically - it has the Qt::Dialog window type rather than Qt::Window. That means any "orphaned" dialog, that is closed, will still prevent the application from exiting automatically.
The solution?
Either giving a parent to the dialog or enabling the Qt::WA_QuitOnClose attribute:
this->_configDialog->setAttribute(Qt::WA_QuitOnClose);