QT Creator accessing pointers to objects - c++

Very new to QT but basically I have a class called object and on my GUI is a one button and one text browser. Now in my class object I have one private QString variable called name and its constructor assigns a value (QString) to the variable called name . The object class has one function called QString getName() const; which returns the name:
class object{
private:
QString name;
public:
object(QString name);
QString getName()const;
};
Now in QT in my mainwindow.h file I put
public:
object *o;
and then in the constructor :
object o2("Name");
o = &o2;
Now I want to call the function void MainWindow::on_pushButton_clicked() and all this function will do is set the text in the text browser to the name variable in my object (which would be "Name" btw) so inside the function I put ui->Console->setText(o->getName()); console being the name of my text browser- when i run the code and click the button its saying that Ive referenced memory and giving an error. Keep in mind I moved ui->Console->setText(o->getName()); to the constructor and it worked perfectly (obviously didnt work when the button was clicked but the text was put in the text browser) so what am I doing wrong here ?

The pointer (o) outlives the object that it points to (o2). One way to fix it is by allocating new memory for the object:
o = new object("Name");
And then you'll need to remember to delete that memory later.

Related

Can I create a pointer to an object in the constructor of said object?

The goal is that every time I create an object of my Car class, a pointer of this object is then created and placed in the "car registry".
This is what I have:
class Car {
private:
string color = "blah blah";
string make = "blah blah";
string model = "blah blah";
public:
Car(CarRegisterManager* carRegisterManager) {
// This is where I want to "register" any object of this class with a pointer
// to reference of this created object inserted into the CarRegisterManager's vector or
// registered cars.
carRegisterManager->registerCar( /*pointer goes here*/ );
}
}
class CarRegisterManager {
private:
std::vector<Car> registeredCars_;
public:
void registerCar(Car* car) {
registeredCars_.push_back(car);
}
}
int main() {
CarRegisterManager carRegisterManager;
CarRegisterManager* p_carRegisterManager = &carRegisterManager;
Car hondaCivic1(p_carRegisterManager); // When this is created, I want a pointer to it registered.
}
As you can see, part of my solution was to upon creation of the CarRegisterManager to create a pointer to the manager object to include as a parameter in the constructor of any Car object, then having the constructor do something with that. I know I need to use a "this" or something to indicate that this created Car object needs a pointer created for it, and then this pointer is put into the CarRegisterManager's registerCar function.
I'm still struggling with the concept of using keywords new and this, if that is indeed what I would need to use here. I apologize if this is answered somewhere else. I legitimately searched for a while before posting this. I may not be using the correct key terms to set these things up.
Thanks.
You already know the answer, because you state it in your question:
I know I need to use a "this" or something to indicate that this created Car object needs a pointer created for it, and then this pointer is put into the CarRegisterManager's registerCar function.
You can use the literal this pointer, eg:
Car(CarRegisterManager* carRegisterManager) {
carRegisterManager->registerCar(this);
}

Binding instance of C++ object to QML object

I'm new to Qt, and have written a basic application which has one class which inherits from QObject and is bound to a QML file.
I now want that class to contain a Vector of objects (let's say from a class Customers), which contains some data, such as a QString for name, etc.
To make life easier I'll create these objects manually in main, and place some text fields in my QML file.
I now want to be able to bind specific objects to specific text fields in the QML file, such that when a value changes, the value in the text field updates.
How can this be done? It looks like QML statically calls methods of the classes it's bound to, instead of on an assigned object.
I feel like QAbstractList may have some use here, but not too sure. Would rather not have to inherit from anything for my Customers class.
EDIT:
I think I may be able to do what I want with a QObjectList-based Model (https://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html). I notice it says at the bottom that "There is no way for the view to know that the contents of a QList has changed. If the QList changes, it is necessary to reset the model by calling QQmlContext::setContextProperty() again."
Does this mean that if a value inside DataObject (such as name) changes, the model has to be reset, or only when the Qlist itself changes (i.e. new item added, or item deleted)? If the latter, I would think this should be fairly easy to maintain as I would only need to set the context property whenever anything is added or deleted.
This may be usefull if you want to process raw QObject instance in QML script. You can append properties to Element class and modify them from qml.
class Element : public QObject {
Q_OBJECT
private:
QString type;
QLinkedList<Element*> child;
public:
explicit Element(QString type, QLinkedList<Element*> child);
virtual ~Element();
public:
QLinkedList<Element*> getChild() const;
QString getType() const;
public:
static void printTree(Element* root);
};
this is so simple you need to use NOTIFY
define your properties like this :
Q_PROPERTY (QString name READ name WRITE setName NOTIFY nameChanged)
then you need to define each one like this :
public : QString name() const;
signals :
void nameChanged(QString name);
public slots:
void setName(const QString &name);
private QString _name;
and then you should define body in cpp like this :
QString className::name() const{
return _name;
}
void className::setName(const QString &name){
if(name==_name) return;
_name = name;
Q_EMIT nameChanged(_name);
}
after registering it to QML with qmlRegisterType<ClassName>("com.className",1,0,"className");
simply set name it will notify if it changes for example in a textfield set text to that name property

how to create static QLabel in Qt

Is it possible to create some static QLabels in one class, and other classes can access its QLabels variable and apply changes to the QLabels without creating its object?
I found some answers online like if you want to access one class variables without creating its object in another class, you have to make its data static.
So basically what I am trying to do here is accessing and changing one class variables, for me it is QLabels, in another class without creating its object.
I know how to create static variables, but when comes to declare a staic QLabel, I found it difficult to achieve it.
I think you may just make the label accessible, i.e. expose it as a public member. Say you have a Form class, and a label QLabel in its ui. Add this method to the class:
public:
QLabel * label();
the implementation is just:
QLabel *Form::label()
{
return ui->label;
}
If all you need to expose is the label text property, just add these two accessors methods:
public:
QString labelText();
void setLabelText(QString & text);
in implementation file:
QString Form::labelText()
{
return ui->label->text();
}
void Form::setLabelText(QString &text)
{
ui->label->setText(text);
}
These last strategy fits encapsulation better.
About having it static: what if you have more than one instance of the Form class? Which label is supposed to be pointed to by the static member? If you are 100% sure you will have only one instance of the widget, you can add a static public QLabel * member:
public:
static QLabel * label;
in implementation file, on top:
QLabel *Form::label = 0;
in Form constructor:
ui->setupUi(this);
if(label == 0)
{
label = ui->label;
}
Again, this makes sense if you have one Form instance only. Otherwise, the static pointer will point forever to the label of the widget which was created first (and, dangerously, to nothing when that instance gets destroyed).

Classes, Objects, Treewidget and QlistWidget

I'm trying to create a program for a project in school (University).
The program is basically supposed to have a QTreeWidget with a bunch of components, the QTreeWidget will update when you click on a button (for example Chassis-button will change the QTreeWidget into a bunch of different chassis).
From the QTreeWidget, you're then supposed to be able to mark one that you want and click on a "choose-button" which will transfer that row to a QListWidget. One example of a row could be :
"Fractal Design"
"R3"
"100euro"
"ATX"
I have a bunch of classes for each component. One of the classes is Chassis and it has a function named addChassis which looks like this :
void ChassisHandler::addChassis(string manufacturer, string model, int price, string size, string color, int fanSpots) {
Chassis **temp = new Chassis*[this->nrOfChassis + 1];
for (int i = 0; i < nrOfChassis; i++)
{
temp[i] = this->chassis[i];
}
delete[] this->chassis;
this->chassis = temp;
this->chassis[this->nrOfChassis] = new Chassis(manufacturer, model, price, size, color, fanSpots);
this->nrOfChassis++;
}
This function works fine if I want to create a class object and add a few chassis into the object and then print out the object, but I can not use it to add chassis into the treewidget. It needs to be QString instead of string and int and Qt seems to have a problem with me making a class object and then transfer the object to the treewidget. I simply do not have enough knowledge to be able to put all the chassis into the QTreeWidget. Right now I've created an additional function in my .cpp file that belongs to the .ui file which look like this :
void Computer::AddChassi(QString manufacturer, QString model, QString price, QString size, QString color, QString fanSpots){
QTreeWidgetItem *itm = new QTreeWidgetItem(ui->treeWidget);
itm->setText(0, manufacturer);
itm->setText(1, model);
itm->setText(2, price);
itm->setText(3, size);
itm->setText(4, color);
itm->setText(5, fanSpots);
}
But if I try to put this function in the Chassiclass, it says that "UI is not defined". It's very important that we use classes in this project.
So my two problems are :
How to create proper addfunctions to put strings into my TreeWidget?
How to transfer the wanted string from my TreeWidget to my ListWidget?
if I try to put this function in the Chassi class, it says that "UI is
not defined".
Your AddChassi() method looks mostly correct, except of course you are trying to dereference a variable named "ui" and (it appears that) there is no member variable named "ui" that is part of your Computer class, which is why you get that compiler error. Presumably the pointer "ui" is one that is available for use only in other contexts (e.g. because it is a member variable of another class), so making it available for use inside AddChassi() is just a matter of passing it in -- you could pass it every time as one of the arguments to AddChassi() if you want, or you could pass it in to the Computer class's constructor and hold it as a member variable of the Computer class for later use. Or, perhaps better yet, instead of passing in the ui pointer, just pass in the pointer to the QTreeWidget object, since that is the only thing you really need to pass in to the QTreeWidgetItem constructors anyway.
For example:
void Computer::AddChassi(QTreeWidget * tw, QString manufacturer, QString model, QString price, QString size, QString color, QString fanSpots){
QTreeWidgetItem *itm = new QTreeWidgetItem(tw);
[...]
my Second problem is to transwer the wanted string from my TreeWidget
to my ListWidget
The QTreeWidget class has various accessor functions (such as currentItem() and topLevelItem()) that you can use to obtain a pointer to one of the QTreeWidgetItems objects current attached to the QTreeWidget. Once you have that pointer, you can call the QTreeWidgetItem::text(int) method on it to extract the QString representing the text in the nth column of that item's row. Once you have that QString you can use it to create a new QListWidgetItem with that QString as its constructor argument.

QT calling functions in different sources

In my project I've created multiple gui pages. In a secondary source (secondary.cpp) I want to call a function that declared in my mainwindow.cpp. I'm not really sure how to do this.
I've tried to declare the function at public section like:
QString format (QString number);
And definition in the mainwindow.cpp like:
QString MainWindow::format(QString number)
{
...
}
Then i include #include "mainwindow.h" in my secondary source (secondary.cpp) and calling the function with lower = format(upper); but I'm getting an error message:
format was not declared in this scope.
I've also tried calling it by
lower = MainWindow::format(upper);
which gives me the error message
Cannot call member function QString MainWindown::format(Qstring)
without object.
Finaly I also tried to make a class in my mainwindow.h
class test : public QString
{
public:
QString format (QString number);
};
With QString test::format(QString number) in my mainwindow.cpp calling the function by lower = test::format(upper);
this gives me the error:
Cannot call member function QString MainWindown::format(QString)
without object.
I'm not convinced that I need to create a new class, but I thought I'd try anyway.
You need to create object of MainWindow class, then call function:
MainWindow *w = new MainWindow;
QString lower = w->format(upper);
Or another solution is static function of class. This way you have no needed create object of class and can call method by name like this:
QString lower = MainWindow::format(upper);
Of course you need to include your #include "mainwindow.h" header.
But you should know that MainWindow class is not the best place storing function for formation string, you can use QString class function like QString::toUpper() or QString::toLower() or create your own class for formating:
class myFormatingStringClass {
QString toLower(QString str);
static QStrin toUpper(QString str);
}
As i said above this way you will need to create object of myFormatingStringClass for using myFormatingStringClass::toLower() function or using static method:
QString upper = QString("Hello World");
myFormatingStringClass formating;
QString lower = formatin.toLower(upper); // Using class method of existing object
QString upper = myFormatingStringClass::toUpper(lower); // Using static method
You can't do test::format(...) to call a non-static member function.
It must be bound to an object (an instance of your class). For example, you can do this :
test testObject;
QString formattedString = testObject.format(strToFormat);