I have a window(.ui file) and at certain point i want to erase everything inside of it and repaint a new interface by connecting a new .ui file to that class without creating seperate class. Is there a way to do it?
The task sounds like a good job for QStackedWidget. With its help you can design different widgets (aka "pages") conveniently in the designer, and switch between them inside your code using setCurrentIndex() and/or setCurrentPage().
I'm currently working on a Qt project and am somewhat confused with the signals and slots mechanism. I feel however that I have a somewhat good understanding between the differences between a QObject and user interface form.
A user interface form (described by a .ui file) is fed into the user interface compiler(uic) and produces an associated header file. This header file doesn't just contain interface information, but instead contains the implementation details on a QObject should be formatted. A QObject on the other hand is the base class in which a lot of the Qt framework is built upon. The signals and slot systems is based completely on the QObject.
When extending the QObject class (or from a derived class), you are actually defining an object in which can produce signals and slots. To format this object to look like the user interface you just designed in Qt Designer, you create an instance of the ui class (via the ui header generated by the uic). You call the setup method on this class and feed it the new QObject you're creating.
This all seems to make sense.
However, what doesn't make sense is when you start actually defining signals. From with Qt Designer, I have the option to right click and select a 'signal'. When I select a signal (whether that be a mouse click on a button or a change in a progress bar), it ends up adding that to my QObjects signals section. My question is: why and how? How exactly are my actions in Qt Designer (a program that generates an XML for the uic) getting coupled to my QObject in Qt Creator? More specifically, how does it know which QObject to add this slot to?
This question may be somewhat unclear, so I'll throw an example here.
Say for example I want to create a new interactive display of some kind. Let's call it 'MyScreen'. In order to create this interface, I would likely have 3 files: 'myscreen.h', 'myscreen.cpp', and 'myscreen.ui'. 'myscreen.h' is responsible for declaring the QObjects properties and methods as well as signals and slots. 'myscreen.cpp' is responsible for defining the methods, signals, and slots. 'myscreen.ui' is repsonible for creating the user interface layout that will be used to format an instance of MyScreen.
But due to what I had stated previously saying that the ui is just used for generating a header, why exactly is it coupled to 'myscreen.cpp'? That is, I can right click on the .ui layout, create a new signal type, and that signal type will be added to the myscreen.h and myscreen.cpp. How does this happen? How is it coupled? Does Qt operate such that there should always be 3 files (xxx.h, xxx.cpp, xxx.ui) that should exist?
So hopefully that gives you some context in what I'm confused about. There doesn't seem to be a well written document (that I've found at least), that thoroughly describes the underlying relationship between all these items.
TLDR - How does the signal/slot from the .h and .cpp actually link to the elements defined in the .ui file?
My question is: why and how? How exactly are my actions in Qt Designer (a program that generates an XML for the uic) getting coupled to my QObject in Qt Creator? More specifically, how does it know which QObject to add this slot to?
The short answer is: magic.
The real answer is, it actually has nothing to do with your actions in Designer, at least not directly. It's not actually even a UI-specific thing, it's just that designer makes good use of it. What happens is this:
First of all, any time you compile a file that makes use of the Q_OBJECT macro, this triggers Qt's moc tool to run during compilation ("triggers" isn't really the most accurate description: More precisely, when qmake is run to generate makefiles, it adds build rules to run moc when Q_OBJECT is detected in a header, but that's beside the point). Details are a bit outside the scope of this answer but long story short is it ultimately generates those moc_*.cpp files you'll see after compilation, which contain a whole bunch of compiled meta info. The important part of this is where it generates run-time accessible information about the various signals and slots you have declared. You'll see how that's important here below.
The other important thing is all QObjects have a name. This name is accessible at runtime. The name you give your widgets in designer is set as the widget's object name. The reason this is important will also become clear below.
And the final important thing is QObjects have a hierarchical structure; when you create a QObject you can set its parent. All of the widgets on your form ultimately have the form itself (e.g. your QMainWindow-derived class) as their parent.
Ok, so...
You'll notice in source code Qt generates for your windows you always have that ui->setupUi(this) call in the constructor. The implementation of that function is generated by Qt's uic tool during compilation, in e.g. ui_mainwindow.h. That function is where all the properties you set up in designer, stored in the .ui file, are actually set, including the widgets' object names. Now, the last line of the generated setupUI() implementation is the key:
void setupUi(QMainWindow *MainWindow) {
...
// Object properties, including names, are set here. This is
// generated from the .ui file. For example:
pushButton = new QPushButton(centralWidget);
pushButton->setObjectName(QString::fromUtf8("pushButton"));
pushButton->setGeometry(QRect(110, 70, 75, 23));
...
// This is the important part for the signal/slot binding:
QMetaObject::connectSlotsByName(MainWindow);
}
That function, connectSlotsByName, is where the magic happens for all those widget signals.
Basically that function does the following:
Iterate through all your declared slot names, which it can do because this was all packed into runtime-accessible strings by moc in the meta object info.
When it finds a slot whose name matches the pattern on_<objectname>_<signalname>, it recursively searches the object hierarchy for an object whose name is <objectname>, e.g. one of your named widgets, or whatever other named objects you may have created. It then connects that objects signal, <signalname> to the slot it found (it basically automates calls to QObject::connect(...)).
And that's it.
So what this means is, nothing special actually happens in designer when you go to a slot there. All that happens is designer inserts a slot named on_widgetName_signalName, with the appropriate parameters, into your header and generates an empty function body for it. (thuga has added a great explanation of this). This is enough for QMetaObject::connectSlotsByName to find it at run time and set up the connection.
The implications here are very convenient:
You can remove a widget's signal handler without doing anything special in designer. You just remove the slot and its definition from your source file, it's all completely self contained.
You can add widget signal handlers by hand without having to go through the designer interface, which can save you some tedium sometimes. All you have to do is create a slot in your window named e.g. on_lineEdit1_returnPressed() and voila, it works. You just have to be careful, as hyde reminds us in a comment: If you make a mistake here you won't get a compile-time error, you will only get a run-time warning printed to stderr and the connection won't be created; so it's important to pay attention to console output if you make any changes here.
The other implication here is that this functionality isn't actually limited to UI components. moc runs for all your QObjects, and connectSlotsByName is always available. So any object hierarchy you create, if you name the objects, then declare slots with appropriate names, you can call connectSlotsByName to automatically set up connections; it just so happens that uic sticks that call at the end of setupUi, because that's a convenient place to put it. But the magic isn't UI-specific, and doesn't rely on uic, only on the meta info. It's a generally available mechanism. It's pretty neat.
As an aside: I stuck a quick example of QMetaObject::connectSlotsByName on GitHub.
What happens when you add a slot from the Go to slot... context menu item, is it goes through your project, and it looks for any files that include ui_myclass.h. When it finds this file, it then makes sure that Ui::MyClass object is declared either in that file, or in directly included files. These would be your myclass.cpp and myclass.h files. If it finds these files, it will then add the slot declaration and the definition in those files.
You can test this by removing the Ui::MyClass object (usually named ui) declaration from your myclass.h file, and then adding a slot by using the Go to slot... function in the designer. You should get some error message stating it couldn't find Ui::MyClass object declaration.
You can also try removing the ui_myclass.h inclusion from your myclass.cpp file. If you try adding a slot from the designer now, you will get an error message stating that it couldn't find ui_myclass.h included anywhere, or something like that.
If you define everything just inside your myclass.h file and remove myclass.cpp, it should give you an error message stating that it is unable to add the slot definition.
You can inspect how it works in more detail by looking at this part of the source code.
But in the end what really matters is, that you declare and define your class methods in separate .h and .cpp files, and that ui_xxx.h is included and that Ui::xxx object has been declared in those files. Of course this is what Qt Creator does for you automatically when you add a new form class, so you don't have to worry about it.
this is my first question on this website, but I will try to cover everything that is needed. Apologies if I forgot something. I encountered the problem using QT Creator, but I suppose it would be the same using Visual Studio, or just C++ in general.
I've got a couple of classes: Mainwindow, Track and AddForm. Mainwindow is what it is called. The main form. Track is a custom class based on QObject which contains just a single QString variable (just for now, since I am still experimenting with QT). And AddForm is a class for another form that can be created by clicking a button in my MainWindow form. That form only contains a single line-edit to fill the string and a button that says "Add". Whenever that button is pressed the text from the line-edit will be put into the QString variable from the Track-class. That QString variable is called "artist".
Apart from assigning the text from the line-edit to the variable "artist" for the Track-object, the form will also emit a signal that sends that entire object. A slot within my mainwindow will react to that signal and collect the Track-object. So far so good.
Here is my question. Within my mainwindow-header I have created a private QVector named trackVector, which I can then call within my mainwindow.cpp. What I want to do is append / push_back the QVector with that Track-object. Sort of like this:
trackVector.push_back(trackObject);
I get the following error message when building the application:
click here for a screenshot
Now ofcourse with an integer or any other variable this is very straightforward. You would just do something like this I suppose:
QVector<int> myVector;
myVector.push_back(3);
I think that whenever you append a QVector (or a standard non-QT vector) you need to do so with the constructor of that class. But how can I make a constructor in which you can just put an already existing object?
Please explain with as much simple words as possible since I am no native English speaker :) Thanks a lot in advance!
You've posted insufficient code (so your post is liable to be closed as off topic -- a classical beginners error on SO), but I guess the appropriate solution here is to use some auto pointer type. If your TrackVector is to keep ownership of the Track objects, then the best solution is have std::unique_ptr<Track> elements:
std::vector<std::unique_ptr<Track>> TrackVector;
// filled like
TrackVector.emplace_back(new Track(args));
If, on the other hand ownership lies somewhere else, you may either use std::shared_ptr or even raw pointers (provided your layout guarantees that the pointed to Track objects' lifetime exceeds that of the TrackVector).
I want to dynamically instantiate a QWidget and bind its "Pressed" event, either with a Qt signal or by overriding a function.
However I'm only allowed to create one new .cpp file.
I don't know how to override a C++ function dynamically, or how to change a virtual function into a Qt signal.
Is what is represented in the picture above achievable ?
The Widgets Tutorial of the Qt docs is a nice starting point.
Under Qt Widgets Examples you can find the Calculator Example, which should contain all of what you want to do.
Take the code, strip it down to what you need, use and try to understand it.
Or maybe have a look at the Getting Started section.
In my application the main window's GUI is designed in the Qt-Creator designer. I have had some trouble in getting it to look just the way I'd like, but I can when doing the GUI in C++ code.
So, I plan to change the application's main window to be laid out in code.
What should I keep in mind when doing this?
How do I make sure all the menu items and button clicks etc. get migrated, too?
In my Qt experience I almost always write layout in code and here is what I can suggest:
a) Spend some time thinking which Layout to use, personally I tend to use either QGridLayout or nested QHboxLayout and QVBoxLayout which give you lot of flexibility.
b) I normally declare all child widgets as class variables always pointers and I create the real objects in the Main windows constructor.
About not to forget any control I suggest to print the XML of the UI file and draw a line on each control you recreate in the code.
As a good starting point, simply copy-pase the setupUi method from the ui_xxx.h file that uic had generated for you. You can then manually edit the setup code to suit your needs.