Connecting QDialog to QMainWindow - qt

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.

Related

Qt is activating window without my consent after using QFileDialog

Qt 5.12.6 MSVC2017 64-bit on Windows 10, Qt Creator 4.10.1.
I have a top level window derived from QMainWindow, which has a QMdiArea.
From the first main window I use a file open dialog to open a new document in a QMdiSubWindow and place it in the QMdiArea. After the file dialog returns but before I do the logic of opening the document, I have to call QApplication::setActiveWindow(this), to set it back to the main window, because the opening logic depends on the active window. The need for this somewhat appears related to https://www.qtcentre.org/threads/2950-ActiveWindow-changes-after-closing-QFileDialog in that the activeWindow becomes null, regardless of how I parent the file dialog.
I then open a second identical top level window and open another document using the same method.
What's very weird is that after the second QMdiSubWindow in the second QMainWindow is activated, the first QMainWindow gets activated again, and thus various follow-on operations affect the document in the first window rather than the second window which is the intended one. If I click back and forth on the main windows, the activation is correct.
If I create a new document directly from the second QMainWindow instead of using the file open dialog, then it works fine. The new QMdiSubWindow is created and shown in the second QMainWindow, without the first one getting activated. So this implicates the file dialog somehow.
When I put a breakpoint on a function triggered by the QMainWindow::activated signal, the stack trace shows this signal is coming from within Qt on its own accord, not from someplace in my code directly.
How can I find out why Qt is activating the first window when using the file dialog from the second window? At this point the code is too large to try to fit a minimal example here on SO.
--EDIT--
I added a one-shot QTimer at the end of the function that creates the QMdiSubWindow. Zero milliseconds after in creates the QMdiSubWindow it activates the first QMainWindow, then activates the current QMainWindow. That workaround seems to work, and the second QMainWindow becomes the active one. But only if I select away from it first. The fact that the hack works with 0 ms timer is also interesting. I'll be posting minimal example when I can.
thanks

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

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.

QT designer implementation error

Actually i activated the Qt creator from terminal ex: in Linux sudo Qt-creator.sh. so qt application opens.when i tried to design the UI by drag and dropping the buttons , widgets to form a type of UI.when i run the application , it just show the blank widget. the designed part done in UI is not implemented. so whatever changes done in UI designer, is not displaying when i run application. i don't no where is the issue. is it because of activating the qt from terminal.
the reason for activating qt creator from terminal because, i need to cross compile the binary code for Arm-Cortex controller. so i need to follow the steps for setting compiler for arm-cortex in qt application.however the cross compilation works. but if any changes done on qt designer, when i run the application , i cant able to see the changes in UI output window.
Let me start by providing some background.
The Qt library allows you to create graphical user interfaces (GUI) using two alternative methods:
QWidgets
Qt Quick
QWidgets uses a set of widgets written in C++ that you can either create and layout yourself using explicit C++ code, i.e. manually, or use Qt Designer to edit the interface of your applicaiton in a WYSWIG style, producing a .ui. file that you use in a certain way later on.
Qt Quick uses a declarative approach to creation of the user interfaces, with a special markup language similar to HMTL. We're not discussing it here as it's not the approach that you're using.
Now let's take a closer look at how Qt Designer works in conjunction with .ui. files, given that our application is written in C+.
Once you launch Qt Designer and edit a form, then save it, a .ui. file is produced. It's an XML file containing an hierarchical description of the UI you've created. However, to be able to use that form as the GUI of your application, additional steps are required. You need to "tell" the application to use this .ui. file. This is done as follows. A special executable, the UI compiler uic, is invoked (automatically via qmake or cmake) to process the .ui file, and generate C++ code in form of a header file. You then include the header file in the file that includes your application code, and use one of the three available methods to create the UI of your application using the generated code.
The simplest method is shown below.
class MyForm : public QWidget
{
Q_OBJECT
public:
MyForm(QWidget *parent = 0);
private:
Ui::MyForm ui;
};
The ui member object is an object of the class generated by uic - the UI compiler mentioned above. The class contains code for creating the user interface, organizing it into a layout, and managing it throughout the application lifetime.
Then, in the .cpp file, we have the constructor:
MyForm::MyForm(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
}
The important call here is ui.setupUi(this). This creates the UI elements, applies the layout, and sets the layout on the widget provided as the argument to this call. Remember, our class inherits from QWidget.
The other approaches include inheriting from the generated class and dynamically loading the .ui file, omitting the compilation by uic, using the QUiLoader class. Please consult http://doc.qt.io/qt-5/designer-using-a-ui-file.html for further reference.
As far as starting Qt Designer from terminal, it has no effect on the problem. Moreover, starting a GUI application as root is highly discouraged on Linux, as it poses a major security issue.

QFileDialog in a non-QT app

I have an app that uses a 3rd party GUI framework, but I want to open files with using QFileDialog. I'm thinking of instantiating a subclass of QWidget that is invisible and serves the purpose of serving up the dialog.
Is there a better way to do this?
I don't see any need for an invisible widget, since the file dialog doesn't require a a parent widget in order to be shown up.
Since the dialog needs to have a Qt event loop running, you will need to either show the dialog modally using exec(), or using one of the static functions like getOpenFileName.
To use any of the widget classes, including the file dialog, you need to have an instance of QApplication, although that instance doesn't have to have its exec() method called.

How to generate a window (widget) on button press in qt

I have designed a GUI through Qt creator on Linux. This design consists of some fields, text edit and some push buttons.
When I press on the push button I want to display another window. Is there any GUI option for this or any hard code?
You need signals and slots.
You have to connect the clicked signal to a custom slot, created by you, of your main widget.
Corrected Code, based in the comments of Patrice Bernassola and Job.
In the class definition (.h file) add the lines:
Q_OBJECT
private slots:
void exampleButtonClicked();
private:
QDialog *exampleDialog;
The macro Q_OBJECT is needed when you define signals or slots in your classes.
The variable exampleDialog should be declared in the definition file to have access to it in the slot.
And you have to initialize it, this is commonly done in the constructor
ExampleClass::ExampleClass()
{
//Setup you UI
dialog = new QDialog;
}
In the class implementation (.cpp file) add the code that does what you want, in this case create a new window.
void ExampleClass::exampleButtonClicked()
{
exampleDialog->show();
}
And also you have to connect the signal to the slot with the line:
connect(exampleButton, SIGNAL(clicked()), this, SLOT(exampleButtonClicked()));
Your question is somehwat basic, so I suggest to read a basic tutorial, in this way you can make progress faster, avoiding waiting for answers.
Some links to tutorials that were useful to me:
http://zetcode.com/tutorials/qt4tutorial/
http://doc.qt.io/archives/qt-4.7/tutorials-addressbook.html
on click event of button you create another widget and show.
another option is Stacked widget, http://doc.trolltech.com/4.6/qstackedwidget.html

Resources