QCreator puts slot handlers in wrong class.
-
This is a summary that I'm going to mark as the solution, although I'm not 100% sure this is a permanent fix.
QCreator quirks
I encountered a problem with QCreator putting new slot handlers in the wrong class. This made for significant inconvenience in adding new slot handler functions.
I found what I think is a fix for this particular QCreator wonkiness. QCreator appears to get "stuck" on whatever compilation unit it is on when it encounters the first instance of #include "ui_mainwindow.h" and assumes that is your "main" window class. The workaround I found was to make sure that file is included first in the mainwindow.cpp file, and last in any other file that uses it. Where possible, don't even include ui_mainwindow.h at all, but use a forward declaration of the form:
namespace Ui { class MainWindow; }
You will need to do a "reset" of the IDE after implementing this workaround. Detailed instructions from the Qt website:
- Close Qt Creator.
- Use your file explorer to navigate to the folder where your project is stored. Delete the ".pro.user" file that is there, such as Life.pro.user.
- Also delete the "build" folder for your project. This is located in the parent directory of your project's directory, and it usually has a long name like build-Life-Desktop_Qt_5_5_0_MinGW_32bit-Debug . Delete this entire directory.
- Re-open your project's .pro file in Qt Creator. It should ask you to "Configure Project".
-
@HowardHarkness said in QCreator puts slot handlers in wrong class.:
#include "ui_mainwindow.h" and assumes that is your "main" window class
here is actually a more fundamental problem on your part.
ui_ClassName.h should always only be included once, and that is from your ClassName.cpp file. Interpret
ui_mainwindow.h
as a private header of mainwindow.cppwhy do you include it anywhere else , a 2nd time, in your code base ?
-
@J-Hilk said in QCreator puts slot handlers in wrong class.:
ui_ClassName.h
should always only be included once, and that is from your ClassName.cpp file. Interpret ui_mainwindow.h as a private header of mainwindow.cppDouble-plus++. Sounds like a very possible reason.
@HowardHarkness said:
instead of to some random class that seems to change every time I restart Qt.
Do all these "random" classes have
#include "ui_mainwindow.h"
in them? -
@J-Hilk said in QCreator puts slot handlers in wrong class.:
why do you include it anywhere else , a 2nd time, in your code base ?
I separated out parts of the hardware (register groups) into separate classes, and I needed a pointer to the various line edit widgets in the main window to get/set the values. The pointer to the main window was named ui and it was defined as a Ui::MainWindow* in ui_mainwindow.h.
namespace Ui { class MainWindow: public Ui_MainWindow {}; }
There were some .cpp files I couldn't figure out how to get past the compiler without including ui_mainwindow.h. I needed that #include because the ui pointer can't be used without it. When I implement the other parts of the hardware, there will be more of the same sort of problem.
It would appear that might not have been the optimal design... However, it's not immediately obvious what I should have done. Is there something other than a Ui::MainWindow* that I can use to access the line edits? I don't really want to have to pass a separate pointer to each line edit as a parameter. to the hardware classes.
-
@HowardHarkness said in QCreator puts slot handlers in wrong class.:
I needed a pointer to the various line edit widgets in the main window to get/set the values. The pointer to the main window was named ui and it was defined as a Ui::MainWindow* in ui_mainwindow.h
This sounds very very wrong!
To access an instance of a class do what is usually done in Qt/C++:- Pass a pointer to the instance
- Use signals/slots to exchange data between classes
I would strongly suggest to go for 2. This way your other classes do not have to know wnything about the main class. Especially you should NEVER expose internal details (like line edits in main window) to the outside world - this is really bad design.
-
@HowardHarkness said in QCreator puts slot handlers in wrong class.:
I separated out parts of the hardware (register groups) into separate classes, and I needed a pointer to the various line edit widgets in the main window to get/set the values. The pointer to the main window was named ui and it was defined as a Ui::MainWindow* in ui_mainwindow.h.
oh my, I feel the cold sweat running down my spine ! ;-) 😉
So you took the privat Ui-pointer of your MainWindow and passed it to children/member classes/instances, so they could read/write directly from the GUI ?
Yes, that goes against coding guidelines. Usually, in Qt world, one does this via signals and slots.
Your member class instance has a new value you want to display it? Let it blindly emit a Signal it doesn't care what happens with it, emit signal and done. In MainWindow connect the signal of your member to the setter of the widget you want to use to display the value. -> Tight coupling broken.You want to update a member instance with new values from the GUI ? Listen to input finished signal of your widget and connect it with a setter of your other class.
There were some .cpp files I couldn't figure out how to get past the compiler without including ui_mainwindow.h. I needed that #include because the ui pointer can't be used without it. When I implement the other parts of the hardware, there will be more of the same sort of problem.
Working against/around the compiler, usually not a good sign :P
The Ui Pointer as a private variable should really stay privat and exclusive to that one class.It would appear that might not have been the optimal design... However, it's not immediately obvious what I should have done. Is there something other than a Ui::MainWindow* that I can use to access the line edits? I don't really want to have to pass a separate pointer to each line edit as a parameter. to the hardware classes
Like I said, neither the Ui-Pointer nor any other elements of the GUI the pointer points too should be exposed outside of the MainWindow class. Break the tight coupling, it will lead to other problems along the line, like hard/impossible to maintain/refactor code.
Use signal/slots and/or getters&setters
-
@J-Hilk said in QCreator puts slot handlers in wrong class.:
Yes, that goes against coding guidelines.
This is against c++ in general ... :)
-
@HowardHarkness said in QCreator puts slot handlers in wrong class.:
Which brings up another pet peeve -- I wish that QCreator would alphabetize the slot handler entries -- at least in the .h file. I currently do that separately (NotePad++ has a fairly handly sort feature). [...]
Note that you can sort selected lines alphabetically by pressing Alt-Shift-S
-
@andr said in QCreator puts slot handlers in wrong class.:
Note that you can sort selected lines alphabetically by pressing Alt-Shift-S
Thanks!
-
@J-Hilk said in QCreator puts slot handlers in wrong class.:
Use signal/slots and/or getters&setters
I didn't come up with an easy way to generate all of the signals/slots I needed, but I did find a way to automatically generate accessor functions, so that is what I used, although that is probably still not the optimal approach.
So far, the accessor functions appear to work. Now, I'm back to working on my unit test problem -- and I hope that the unit test connect problem was just a red herring caused (possibly indirectly) by my poor design decision concerning passing of the Ui::MainWindow pointer.
-
@andr said in QCreator puts slot handlers in wrong class.:
Note that you can sort selected lines alphabetically by pressing Alt-Shift-S
You can also change how they are sorted in the symbols drop-down by right-clicking on it and then checking 'Sort Alphabetically'. That is a sticky option that then applied to all files.