How to create Widget events before a.exec()?
-
Background
I am working on a project, the main idea is to develop a GUI around the CPP code that I have created.
This GUI will function as a debugger for easy viewing of the information. I am not completely aware of the ways Qt works to create widgets. I created some data members (declared public) in MainWindow class that can be called from main function according to my needs.
e.g.
I want to displaycout
messages of my code as a kind of a log on the widget. So I created a member function that when called takes in "text" and displays it on PlainTextEdit in a read only form.Main.cpp
int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.Display_Log("Hello!"); return a.exec(); }
mainwindow.cpp
void MainWindow::Display_Log(const QString &text) { ui->plainTextEdit->setReadOnly(true); ui->plainTextEdit->appendPlainText(text); }
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); void Display_Log(const QString& text); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
Problem
Now something I noticed is that I cannot create a change in widget until the compiler reaches the pointa.exec()
i.e. if I call this method in a main function of a different C++ project (with multiple in between processes) until and unless the compiler reaches the end of the code it wont be able to continuously display the logging messages I need in between running in the main function.
Also the second problem is that I cannot create a second instance ofMainWindow w; w. Display_Log(" Log info here");
in a different functions as it closes the Widget as soon as its done.
Question
- How can I create an event to display the relevant logging information from different functions and main functions not requiring the code to come to
a.exec()
to wait and register/exit events? - How can I call member functions I created in
MainWindow.cpp
to print or show relevant widgets according to the C++ program I am running?
P.S. Any help would be greatly appreciated.
- How can I create an event to display the relevant logging information from different functions and main functions not requiring the code to come to
-
@Zark_zeugan said in How to create Widget events before a.exec()?:
@JonB
But if i write a.exec() early on won't the program halt in that thread until exit() is called? Isn't that the reason why it is kept in the return statement of the main function?There is a lot to say about all of this, so here are a couple of notes/observations.
You need to get your head around Qt's event-driven paradigm. It is true that the final statement in
main()
ofreturn a.exec()
does not itself return until the UI is exited. However, lots of your code will be called during thata.exec()
, via events/signals/slots..To allow your "other" functions to be called while/after the UI has been shown you could create a
QTimer
before thea.exec()
. They will then be called just after the UI has been shown initially.Another factor to consider is how long your couple of functions will take to run, and whether you need output from them while they are running, rather than when they complete. It is easy to show
call_func_to_perform_task()
's output before proceeding tocall_another_function()
. It is harder if you want to show their output while they are running. Which you may or may not demand. If you do need to show output the moment it is available: you either have to change their code to callQApplication::processEvents()
, which is a little messy, or you would have to move them to a separate thread, which I hesitate to recommend for beginners as so many get this wrong as it's a bit tricky.The neatest way to have them output as they go along is to use a signal with the text they want to show, and a slot which puts that into the desired widget.
-
Hi and welcome to devnet,
Where does these messages originate from ?
The usual in Qt is to use the Qt Logging categories and they use a custom message handler to re-route the messages. -
@SGaist
Okay so I have a C++ code that has its own class and functions, and the main function can run something like this:int main(int argc, char** argv) cout << "Starting a processs" << endl; call_func_to_perform_task() // This output from the function sends information that I need to log in on the debug Widget screen call_another_function() // Display output and log of this as well.
So the functions I call from main can internally generate some data needed to be displayed as logs or can give an output to the main functions that needs to be displayed.
But puttinga.exec()
at the end will mean that I have to wait a long time for all these functions to complete their tasks and then the Qt application being ready to create events that show logs. All I want is to create a GUI with a small text box displaying widget, that shows continuous logs of the processes. -
@Zark_zeugan
Leaving aside the question of how you get the stuff to display from elsewhere (I don't know whether you have an issue there.)The easier Qt way to do this would be to do your
a.exec()
"early". Then invoke your functions to do whatever, once, say you've shown the main window. In other words, let the Qt UI run, then when you do your stuff it's easy to display whatever. -
@Zark_zeugan anywhere inside the mainwidow to launch your app with qprocess or call your cpp run func.
-
@JonB
But if i writea.exec()
early on won't the program halt in that thread untilexit()
is called? Isn't that the reason why it is kept in the return statement of the main function?
Can you please explain with an example code? -
@Zark_zeugan said in How to create Widget events before a.exec()?:
Can you please explain with an example code?
"Then invoke your functions to do whatever, once, say you've shown the main window" - I think what @JonB means is that you do the stuff for example in main window when it is shown. For example, you could use a one-shot timer started in main window constructor and in the slot connected to the timer do what you need.
-
@jsulm
So, in my example I should create a signal to the PlainTextEdit slot and invoke that signal whenever I need to make the changes?
@jsulm
Also How can I call the widgets from a different functions other than the main?
e.g.
MainWIndow.cpp has a public member that can be called from main() by usingMainWindow w; w.Display_Log();
But I want to do this in a different function
But if I create a new instance the widget collapses and the exits unexpectedly -
@Zark_zeugan said in How to create Widget events before a.exec()?:
But I want to do this in a different function
But if I create a new instance the widget collapses and the exits unexpectedlyDon't create a new instance use the existing one!
You can pass w as pointer or reference to that function. -
@Zark_zeugan said in How to create Widget events before a.exec()?:
How do I pass it to a function?
You should know how parameters are passed to functions/methods in C++, this is really basic:
void someFunction(MainWindow &w) { ... } ... MainWindow w; someFunction(w);
-
@jsulm
Thank you and I will do better.So, in my example I should create a signal to the PlainTextEdit slot and invoke that signal whenever I need to make the changes?
Was I correct regarding this?
-
@Zark_zeugan said in How to create Widget events before a.exec()?:
Was I correct regarding this?
I'm not sure what you mean with this. Before you asked about calling something before a.exec() is executed. How is this new question related to this?
-
@jsulm
Yes my question remains the same
You has suggested thatI think what @JonB means is that you do the stuff for example in main window when it is shown. For example, you could use a one-shot timer started in main window constructor and in the slot connected to the timer do what you need.
To which I drew the inference
So, in my case I should create a signal to the PlainTextEdit slot and invoke that signal whenever I need to make the changes?
I only wish to know if it is correct or am I missing something or maybe completely off the mark.
-
@Zark_zeugan said in How to create Widget events before a.exec()?:
@JonB
But if i write a.exec() early on won't the program halt in that thread until exit() is called? Isn't that the reason why it is kept in the return statement of the main function?There is a lot to say about all of this, so here are a couple of notes/observations.
You need to get your head around Qt's event-driven paradigm. It is true that the final statement in
main()
ofreturn a.exec()
does not itself return until the UI is exited. However, lots of your code will be called during thata.exec()
, via events/signals/slots..To allow your "other" functions to be called while/after the UI has been shown you could create a
QTimer
before thea.exec()
. They will then be called just after the UI has been shown initially.Another factor to consider is how long your couple of functions will take to run, and whether you need output from them while they are running, rather than when they complete. It is easy to show
call_func_to_perform_task()
's output before proceeding tocall_another_function()
. It is harder if you want to show their output while they are running. Which you may or may not demand. If you do need to show output the moment it is available: you either have to change their code to callQApplication::processEvents()
, which is a little messy, or you would have to move them to a separate thread, which I hesitate to recommend for beginners as so many get this wrong as it's a bit tricky.The neatest way to have them output as they go along is to use a signal with the text they want to show, and a slot which puts that into the desired widget.