Executing second window causes program to get stuck
-
Hey guys,
Some of this is a generic C++ problem but some of it also seems to be Qt. Basically I have the MainWindow that is there by default and I created a second window with its own class called "ProcDialog". I want this window to pop-up when a button is pressed in the file menu of my MainWindow, which I accomplished. This is how I have the window popup:
#include "procdialog.h" ... void MainWindow::on_actionStart_Calibration_triggered() { ProcDialog CalibPD; CalibPD.setModal(true); CalibPD.exec(); ProcDialog::fnStatusWindowUpdate(); }
As you can see I have a function under the ProcDialog class I have a function called "fnStatusWindowUpdate". I have this function declared as a static under the public section of the class. The problem, is that I am trying to using this second window as a processing status window that reports progress as the program continues, but what keeps happening is that the program seems to get stuck on the line where the second window is created. I want the program to pop-up the second window, and then immediately run that function. But what happens is the window pops up with "CalibPD.exec();" and the line right after (the function) does NOT run until I close the second window that popped up. I am not entirely sure what happened because this wasn't a problem before when I first created the window and I don't remember changing anything that would cause this behavior.
The function itself seems to be OK. This is what it does (for now I just have it with testing filler it will do more later:
void ProcDialog::fnStatusWindowUpdate() { qDebug() << "Working"; }
Once the second window is closed "Working" appears in the Application Output tab. So what I need to know (if anyone can figure this thing out) is how to have it so after the window pops up the program just keeps running as normal. I don't know why it gets stuck on " CalibPD.exec();" and requires the window to be closed to continue.
Thank you for your time.
EDIT:
I tried using "CalibPD.show();" instead which does allow the program to continue but then the second window appears entirely blank with nothing that I added appearing on it.
-
@oblivioncth said:
Hi
CalibPD.exec(); is blocking.
Its a event loop. so its stays in there. (it must)You can use show() to avoid this.'
BUT you code has a classic bug if you use showvoid MainWindow::on_actionStart_Calibration_triggered()
{
ProcDialog CalibPD;
CalibPD.setModal(true);
CalibPD.show();
ProcDialog::fnStatusWindowUpdate();
} <<< here CalibPD is deleted ..so to you show() you must new it
void MainWindow::on_actionStart_Calibration_triggered()
{
ProcDialog *CalibPD= new ProcDialog(this);
CalibPD->show();
ProcDialog::fnStatusWindowUpdate();
}make sure to delete it again;
you can set
CalibPD->setAttribute( Qt::WA_DeleteOnClose, true );
to make Qt delete it when closed. -
Works flawlessly. I had seen on many other posts people talking about making sure objects aren't destroyed before you used them again but I didn't have the experience here to see that was the problem.
You're a life saver. Thanks again mrjj.
-
@oblivioncth
You are most welcome.
And no worries, you will do the show() trick from time to time. I do :) -
Hey, sorry to be a bug, but it seems i have another problem. This is now my function:
void MainWindow::on_actionStart_Calibration_triggered() { ProcDialog *CalibPD = new ProcDialog(this); CalibPD->setModal(true); CalibPD->setAttribute(Qt::WA_DeleteOnClose,true); CalibPD->show(); ProcDialog::fnStatusWindowUpdate(); AR_Main(); }
I now have the additional function call "AR_Main();". This function is under another source file so I have "#include "AR_Main.h" at the top of this file.
The issue is that the contents of the Proc Dialog pop-up window do stick around when ProcDialog::fnStatusWindowUpdate(); is called, but are destroyed (the window goes blank) once AR_Main(); gets called. If I comment AR_Main(); out the window contents are NOT destroyed so it seems to be a particular issue with calling AR_Main(); and not just the function MainWindow::on_actionStart_Calibration_triggered() ending.
-
@oblivioncth said:
hi, npAR_Main();
so what does this function do ?
There should be no reason that CalibPD should be affected.(the window goes blank)
It sounds to me that perhaps you make endless loop ?
in AR_Main(); -
It is a giant function that does a lot of image processing with OpenCV, so its hard to summarize.
I did figure out of more things though that might help.
So when the program hits the line:
CalibPD->show();
The window pops up and is blank. I determined this by setting a break point just before it. When I say blank I just mean its a window with the header bar at the top but the body is just white with none of the window objects I setup. Therefore, the window is still obviously blank while AR_Main is running. I tried stepping through the program to determine when the contents of the window actually appear but stepping past everything only got me into the dissembler and then finally to:
int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); <- Won't go past this }
and wont let me step past "return a.exec();". The window contents only show up when I click "continue" in the debugger so I am not sure what is actually causing them to show up. Maybe it is when the program idles some kind of update routine is called?
I do remember reading under the documentation for "show" under QDialog that using that method would require some kind of update function to be called now and then. Could that have something to do with it?
Basically it seems that the window objects show up sometime after the program idles and I need them to basically appear and be intereactable by the time that "CalibPD->show();" is called.
If it helps I could perhaps make a quick video demonstrating the issue.
-
@oblivioncth said:
return a.exec();
This is the application main loop or event loop.
It runs until application is quit. Think of it as Qt main function allowing
signals and events to work.if
CalibPD->show(); does display as expected if you dont call AR_Main();
i assume it loops / use lots of cpu.
And since its called sort while CalibPD is still displaying then
i assume CalibPD never really got the needed time to fully "paint"try to insert
qApp->processEvents();
Right after CalibPD->show(); -
Just to clarify, I was wrong earlier. I thought that it worked without AR_Main being called but really what was happening is that without AR_Main the program would run through and the contents would eventually be painted. The reason it wasn't working with AR_Main is that there is a line in AR_Main that freezes the program (it was a press enter to continue prompt, I am porting a console app over to this GUI). So when the AR_Main was called the program never got to a point where Qt would paint the window, but without calling it the window would be painted due to the wait for enter prompt never happening. So the issue was actually there all along.
Regardless, adding that command did allow the screen to be painted even while AR_Main was running. I may have to use that command every time I want to update the text edit box i have on that window, but that is ok. I am going to leave this open for the moment because I have really in my gut I might run into another small issue or two while manipulating this window and I want to have it fully working before I close the thread again haha. I only have a couple more things to add so it shouldn't take too long to find out.
You did solve my immediate problem so thanks again. I think that event update command is what I was referring to in my last post.
-
@oblivioncth
Hi
ok, so it was not a heavy loop but an input. :)When you go from console to event based GUI , its important NOT to make
large loops/massive calculations as then the whole GUI will appear frozen.
( a.exec(); is never allowed to run)You can indeed often fix this with
qApp->processEvents(); to allow Qt to function but its not a fix all issues.If the AR_Main will du heavy stuff, you might need to put in its own thread to keep your
mainwindow/dialogs responsive.http://www.informit.com/articles/article.aspx?p=1405544&seqNum=3
-
@oblivioncth
well, Just keep in mind that if u make huge loops, the main window and dialogs will stop
looking alive :) -
I have definitely noticed that while debugging haha. Ok so while you definitely solved the issue of the window freezing, the reason I had some of these function calls in the first place were part of a larger problem. I currently have these two windows, and each of them is in their on class like I previously described. However, the issue is that manipulating these windows usually uses the ui->UIMEMBER->UIFUNCTION method, but ui's scope is only within the .cpp file of each window respectively. ui for mainwindow is different than ui in ProcDialog (obviously). I need to be able to use these functions on these members from .cpp files other than ProcDialog.cpp and MainWindow.cpp.
The reason for a lot of what you just helped me with is that I basically need to run:
ui->pteCalibProcWindow->appendPlainText(qsMesg); //Where qsMesg is a QString
while within AR_Main.cpp. Obviously AR_Main.cpp doesn't know what "ui" is so the way I attacked this problem was with what you were helping me with. The approach was what I am used to doing for situations like this, where you prototype a function in a header file and then include that header in the other source file where you want to use that function. So what I did was make the function:
void ProcDialog::fnStatusWindowUpdate(QString qsMesg) { ui->PshBtnCalibFinish->setEnabled(true); }
within ProcDialog and I prototyped like so:
public: ... void fnStatusWindowUpdate(QString qsMesg);
In other projects I could then just call the function in any .cpp that I included "procdialog.h" in but since the function is within I class I thought that just calling it via "ProcDialog::fnStatusWindowUpdate()" would work. But while I figured that should do the trick (I've made functions in other source files available this way in C before when not dealing with classes or the -> method) I run into a paradoxical problem. Just doing the above, the compiler throws a "illegal call of a non-static member function" when I try to call fnStatusWindowUpdate() in AR_Main. But if I make the function static, that error goes away but then the compiler says:
error: C2227: left of '->PshBtnCalibFinish' must point to class/struct/union/generic type error: C2227: left of '->setEnabled' must point to class/struct/union/generic type
While I don't fully understand the -> architecture it is clear that making a function static interferes with using the -> reference. So it seems like the way I approached the issue won't work.
Is there any simple way to manipulate my QPlainTextEdit that is on my ProcDialog window from AR_main.cpp?
I know that this is something that is not Qt specific, but I have never had to do any C++ codding that require this complex of a program structure until using Qt.
-
hi
- "ProcDialog::fnStatusWindowUpdate()" would work.
To call a function like that requires its to be a static function and its
not normally needed unless for certain use cases.
So that is what "illegal call of a non-static member function" comes from.
To call a function defined in a class, you need an instance of that class
Myclass a; << an instance.
a.print();
or
Myclass *a=new Myclass;
a->print();
notice that non new syntax uses "." and if pointer we use "->"
.print() vs ->print()
- Is there any simple way to manipulate my QPlainTextEdit that is on my ProcDialog window from AR_main.cpp?
Is there anything Qt in AR_main.cpp?
Normally you would use slot and signals for such task but if all of AR_main.cpp is "foreign" then you cannot easy send signals.
You could give AR_main a pointer to ur dialog
AR_main( dialogpointer )
and AR_main could call public functions in this instance.
Not pretty but i fear it will not be your biggest issue :)
- "ProcDialog::fnStatusWindowUpdate()" would work.
-
There is something magic about forums. I swore I tried something just like what you were saying before and it didn't work lol, but now it did!. I must have had a thing or two wrong.
I first just tried to create an arbitrary member of ProcDialog and use that to call the function. It would run but the QPlainTextEdit woudn't show anything. So then I tried chaning AR_Main to be:
int AR_Main(ProcDialog *TEST)
and when I called it from mainwindow.cpp I did:
AR_Main(CalibPD);
Then finally, in AR_Main I wrote:
TEST->fnStatusWindowUpdate("Sample string");
and it did exactly what I wanted.
Thank you for being patient with me and dealing with the fact I have some holes in my knowledge for C++. I can't say this will happen here but I started off just as leachy on another form, but eventually became a well known moderator lol. So trust me, I am learning this stuff as people help me with me it. It just takes some time :). I try to make up for the fact I keep asking questions by at least making my posts clear and well formatted, and so that they don't just sound like "Helps givez me codes".
Cheers.
-
@oblivioncth said:
Ok, its shaping up , super :)"Helps givez me codes".
We do help those too but good questions often get better answers.
Also its clear that you do try to fix it first yourself, so some holes in c++ is no issue.Cheers