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.has a private header of mainwindow.cppwhy do you include it anywhere else , a 2nd time, in your code base ?
-
@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.has 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.hshould 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? -
@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.has 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.:
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.
-
@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.
-
@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 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
-
@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 ... :)
-
@J-Hilk I'm using QCreator 4.11.1 -- updating my development environment is a bit tricky here due to the way my PC is locked down. I have to get permission from IT, which can take days... However, I will look into that. I'm not really sure what the current (or best) version of QCreator is, but I guess I will be able to find that out with some searching.
I was unaware of the "ConnectSlotByName" function, so I wasn't using it (AFAIK -- I just now read the docs for that, and didn't completely understand what that function does). What I generally do is right-click on the widget I want to make a slot handler for, and then click on the "go to slot...", followed by the selection of the slot. In this case, currentRowChanged(int) for a QListWidget.

I can work around the creation in the wrong class by cutting & pasting in the correct class (and changing the classname qualifier). It's a relatively minor annoyance, but what's REALLY annoying is when I want to go to an existing slot handler, and it creates a new one in the wrong class that I have to delete from both cpp and h files, and then do a search separately for the handler. When it actually works, the navigation features of QCreator are really convenient -- when they don't work, it bogs me down and disrupts my train of thought.
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). Then I don't have to do a control-F search to find a slot handler -- I have nearly 100 at this point.
@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
-
@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!
-
@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.:
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.
-
@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
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.
