Why std::thread can't open a QT Dialog? - qt

I want to open a simple QT dialog inside a std::thread, but it crashes after the dialog open success.
std::thread([&](){
DialogWarning* dlg=new DialogWarning();
dlg->setModal(true);
dlg->exec();
delete dlg;
}).detach();
What is the problem with this code?

UI components can only be opened from the main thread (aka the GUI thread).
From Threading basics | Qt 5.13:
The Qt GUI must run in this [the main] thread. All widgets and several related classes, for example QPixmap, don't work in secondary threads.

The main reason that you cannot open the dialog in a different thread has been correctly mentioned by #MarkoPacak.
However, what you can do to fix the problem is to emit a signal in your thread to be captured by a slot in the main thread. Then, in your slot, you can show the dialog.

Related

prevent QApplication::exec from blocking main thread

I have a visual c++ program which creates multiple GUI on the main thread. I want to show a QWidget alongside all the other GUI. Currently, if I call QApplication.exec(), it blocks the main thread until I close the window. Is there any way to prevent the exec function from blocking the main thread or to use QWidget without calling exec?
The method is not blocking the main thread, on the contrary: it allows the event loop to execute, ensuring that the UI remains responsive.
While the widget is shown, all the other GUI will be responsive, as Qt's event loop fully interoperates with the native message queue.
If you want something to happen when a dialog widget gets closed, connect the relevant code to e.g. the dialog's accepted() signal.

A way to connect checkbox state to widget visibility in Qt Designer

Does anyone know if there is a way to connect a state of a checkbox in Qt to an object visibility in Qt Designer? I somewhat new to Qt and and prefer to work with Qt Designer rather than messing with the UI code manually. Qt version I'm using is 4.8.6
Any help is appreciated.
In code (old Qt 4 way):
connect(checkbox, SIGNAL(toggled(bool)), widget, SLOT(setVisible(bool)));
or (recommended Qt 5 way):
connect(checkbox, QCheckBox::toggled, widget, YourWidgetType::setVisible);
In Designer: open the Signals And Slots Editor, connect signal and slot above.
Noticed that signals and slots from Designer are reset sometimes, don't know why. Maybe it is more reliable to connect them in code on widgets setup.
Yes, you can connect the checkbox's toggled(bool) signal to the widget's setVisible(bool) or setHidden(bool) slot in Qt Designer - either in "Edit Signals/Slots" mode using drag-and-drop, or in the "Signal/Slot Editor" dock.
If using the drag-and-drop interface to add the connection, you'll need to turn on "Show signals and slots inherited from QWidget", else setVisible(bool) and setHidden(bool) will not be available for the target widget.

Connecting QDialog to QMainWindow

I have created a QMainWindow using QT Designer. I have components that have signals slots. I've made some non-gui components QObjects so I can also use the signal/slot mechanism.
My next step was to add a modeless dialog. I do not want the dialog to block the main window. I would like the dialog to remain active(somewhere visible to the user or in the background) until the user clicks to close it. I created a modeless QDialog object with designer. The dialog pops up as needed. It keeps the information from the previous session in the text box as well. It's just a filename.
However, when I started to connect the QDialog to the QMainWindow, the signal/slot mechanism does not appear to work.
This is my code:
//In the .h file declared as member of the QMainWindow
ScriptDialog *theScriptDialog;
//In the .cpp file, the constructor of QMainWindow
theScriptDialog = new ScriptDialog(this);
QObject::connect(theScriptDialog, SIGNAL(notifyStartScript(QString)), SLOT (startScripting(QString)));
Maybe I am barking up the wrong tree. Is there a better way to create a pop up window like this?
First see if the connect succeeds: check applications console output for a warning about failed connect, then print return value of connect call.
Then some things to do:
You have the Q_OBJECT macro in scriptdialog.h
You remembered to run qmake after adding new Q_OBJECT classes
Add qDebug print/breakpoint to where notifyStartScript is emitted
Connect something else to startScripting slot, with qDebug print or breakpoint, to verify it gets called
If you have used in-source builds (like just running qmake and make from command line at source dir), then switched to 'shadow build' in separate build dir, make sure the source dir is clean of generated .cpp, .h and .o files.

Is it possible to run several QWidgets in separate threads

I am learning Qt and trying to create application that open documents in tabs of QTabWidget. And I need to have each tab running in separate thread. Is it possible? And if it is, can you please show a simple example.
No, this is not possible. Widgets needs to be always drawn and handled by the main thread, where the event loop is executed.
What you can do is defining some slots for each tab which open a document and connect to to some signals in your threads. This way you can emit a signal if a document should be opened in a tab from a different thread and it will be opened and handled by the event loop thread.

Signal and slot connection in .ui

I have started to play a little with Qt 4. And then I have come across a problem with the Qt Designer.
In the Signal/Slots editor I can only setup the connections that are listed there, and not all the slots are listed.
If I try to add it manualy in the .ui file, the connection would not work.
If I add it in the ui_*.h file it works fine, but then the connection is deleted when I change the design.
Does anyone have any good tips to how I can get around this bug? Or to ask another way:
How can I make the Qt Designer list all the available slots?
By default not all signals/slots are shown. You could try checking the "show signals and slots inheritied from ...." checkbox in the lower left hand corder of the "Configure Connection" dialog that comes up when you try to create a signal.
Beyond that, you can either do what Marcin said and use auto-connections, or manually write connect statements in the constructor of the object that uses the ui.
You might try to use uic's autoconnecting feature.
However you won't be able to see all available slots but if you use the same name in both Designer and code - they should automatically be connected.

Resources