Qt C++ cannot call member function ' ' without object - c++

I keep getting this error:
cannot call member function 'QString Load::loadRoundsPlayed()'without object
Now im pretty new to c++ and qt so im not sure what this means. I am trying to call a function from another class to set the number on some lcdNumbers. Here is the Load.cpp which holds the function:
#include "load.h"
#include <QtCore>
#include <QFile>
#include <QDebug>
Load::Load() //here and down
{}
QString Load::loadRoundsPlayed()
{
QFile roundsFile(":/StartupFiles/average_rounds.dat");
if(!roundsFile.open(QFile::ReadOnly | QFile::Text))
{
qDebug("Could not open average_rounds for reading");
}
Load::roundsPlayed = roundsFile.readAll();
roundsFile.close();
return Load::roundsPlayed;
}
And here is the Load.h:
#ifndef LOAD_H
#define LOAD_H
#include <QtCore>
class Load
{
private:
QString roundsPlayed; //and here
public:
Load();
QString loadRoundsPlayed(); //and here
};
#endif // LOAD_H
And finally the place where i call the function:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "load.h"
#include <QLCDNumber>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
MainWindow::startupLoad();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::startupLoad()
{
ui->roundPlayer_lcdNumber->display(Load::loadRoundsPlayed()); //right here
}
When i run this i get that error. Im not sure what it means so if anyone could help i would be thankfull. Thanks.

The error description is pretty clear
cannot call member function 'QString Load::loadRoundsPlayed()'without object
You cannot call member functions, that are not static, without creating instance of the class.
Looking at you code, you probably need to do this:
Load load;
ui->roundPlayer_lcdNumber->display(load.loadRoundsPlayed()); //right here
There are two other options:
make loadRoundsPlayed static and roundsPlayed static, if you don't want them to be associated with the concrete instances OR
make loadRoundsPlayed static and return QString by copy, that will be locally created inside the function. Something like
:
QString Load::loadRoundsPlayed()
{
QFile roundsFile(":/StartupFiles/average_rounds.dat");
if(!roundsFile.open(QFile::ReadOnly | QFile::Text))
{
qDebug("Could not open average_rounds for reading");
}
QString lRoundsPlayed = roundsFile.readAll();
roundsFile.close();
return lRoundsPlayed;
}

Because the method and member are not associated with class instances, make it static:
class Load
{
private:
static QString roundsPlayed;
public:
Load();
static QString loadRoundsPlayed();
};
If you want them to be associated with instances, you'll need to create an object and call the method on it (it doesn't have to be static in this case).

In Load::loadRoundsPlayed(), you should change
Load::roundsPlayed = roundsFile.readAll();
to
this->roundsPlayed = roundsFile.readAll();
or simply
roundsPlayed = roundsFile.readAll();
This particular example won't fix the compiler error, but it illustrates where you are having some confusion with the syntax. When you prefix a function or variable name with "Load::", you are saying that you want the field that belongs to this class. However, every object of a class will have its own copy of the variables that you have declared in it. This means that you need to create an object before you can use them. Similarly, functions are bound to objects, so you again need an object in order to call a member function.
The other option is to make your functions static so that you don't need an object to call it. I strongly encourage you to learn about the difference between instance functions and static functions of a class so that you can use these two tools appropriately when the situation calls for it.

Related

How do I declare a variable to use in a function in C++ Qt?

I'm a beginner in C++. I was making a test application in Qt and came across this problem: Where do I have to declare a variable in order to use it in a function like on_pushButton_clicked() ?
I tried making a main function and declaring the variable there and always got this error when changing the variable in another function:
error: reference to non-static member function must be called; did you mean to call it with no arguments?
Then I tried declaring the variable directly (not in any function) but that didn't work either.
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
int main() {
int x = 0;
return 0;
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
x++; //here's the error
ui->label->setText("number is:");
}
Is there a way to declare that variable (x) so that I can access it through on_pushButton_clicked()?
I managed to make it work: the problem was that I couldn't find, at first, the header file containing the class. That's where I should have declared my variable.

Qt access mainWindow in a class without giving the object to it

I need to access the mainWindow object in a different class. The problem is, that I can not give mainWindow to this class (I don't want to do this, it would make everything much more complicated). Question: Is there any way in C++ or Qt to put an object in something like a local "database" or sth where every other class in the project can look into and communicate with the objects.
What I want to have in the end is something like this:
// A.h
#ifndef A_H
#define A_H
class A{
public:
A() { /*here comes the ting*/ myMainWindow->sayHi(); }
};
#endif // A_H
// MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "a.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
A *a = new A;
}
MainWindow::~MainWindow(){delete ui;}
MainWindow::sayHi(){
// just do anything
}
I don't think, this is possible, but I give it a try...
Thanks for answers!
I need to access the mainWindow object in a different class. The
problem is, that I can not give mainWindow to this class (I don't want
to do this, it would make everything much more complicated).
That is doable. The author don't want to expose the "main window" variable holding the reference or pointer to the object. And, obviously the author wants that UI object to be callable from other objects. In Qt that implies either both objects on UI thread or communication is via queued signal-slot connection only. But the direct call wanted, hence on the same thread.
Is there any way in C++ or Qt to put an object in something like a
local "database" or sth where every other class in the project can
look into and communicate with the objects.
Local thread storage is a known pattern to implement things like that. Qt has own implementation of it called QThreadStorage. You can attempt something like that:
// myLts.h
void ltsRegisterObject(const QString &key, QObject *object);
void ltsRemoveObject(const QString &key);
QObject* ltsGetObject(const QString &key);
template <typename T> T* ltsGet(const QString &key) {
return qobject_cast<T*>(ltsGetObject(key));
}
// myLts.cpp
static QThreadStorage<QMap<QString, QObject*> > s_qtObjects;
void ltsRegisterObject(const QString &key, QObject *object)
{
s_qtObjects.localData().insert(key, object);
}
void ltsRemoveObject(const QString &key)
{
if (!s_qtObjects.hasLocalData())
return;
s_qtObjects.localData().remove(key);
}
QObject* ltsGetObject(const QString &key)
{
QObject *object;
auto it = s_qtObjects.localData().find(key);
return it != s_qtObjects.localData().end() ? it.value() : nullptr;
}
Register main window object in LTS:
#include "myLts.h"
// ...
// register main window in LTS
ltsRegisterObject("mainWindow", &mainWindow);
Find and use the object:
#include "myLts.h"
// ...
// use main window from LTS
auto* pMainWnd = ltsGet<QMainWindow>("mainWindow");
if (pMainWnd)
pMainWnd->show();
P.S. I did not compile this. But it is not hard to fix if so.

C++ QT5 dynamic property

I am using a widget with Q_PROPERTY entries. Now, I do have an internal map, and for each entry in that list has I'd like to add a dynamic property (name e.g. "entry1Color").
I can add a dynamic property via setProperty("entry1Color", Qt::green); successfully, but I don't have a clue where the value (Qt::green) is being transferred to.
How to connect that set value to my map?
When you use setProperty, this value is stored directly in your QObject, and you can use the property getter to retrieve it. The value is returned as a QVariant, so you will have to cast it to the appropriate type. Example for a color:
// The boolean returned indicates if this is a newly created
// or existing properly
bool was_just_create = myObject->setProperty("myColor", QColor(Qt::green));
// [...]
// And read it later on
QColor color1 = myObject->property("myColor").value<QColor>();
Properties declared explicitly with Q_PROPERTY are accessible in the exact same way, with the property getter. This is the same mechanism that is used by the QML engine to access your object properties, with setProperty and property.
Qt consistently use setValue() for setters, and value() (note the absence of get) for getters. Which is probably why you missed the getter in the first place :).
When you are using QObject::setProperty on instance of QObject, it will be saved internally in QObject instance.
As I understand you want to implement it as QMap with value as member variable.
Here how it can be implemented:
testclass.h
#ifndef TESTCLASS_H
#define TESTCLASS_H
#include <QObject>
#include <QMap>
#include <QColor>
class TestClass : public QObject
{
Q_OBJECT
public:
explicit TestClass(QObject *parent = 0);
// mutators
void setColor(const QString& aName, const QColor& aColor);
QColor getColor(const QString &aName) const;
private:
QMap<QString, QColor> mColors;
};
#endif // TESTCLASS_H
testclass.cpp
#include "testclass.h"
TestClass::TestClass(QObject *parent) : QObject(parent)
{
}
void TestClass::setColor(const QString &aName, const QColor &aColor)
{
mColors.insert(aName, aColor);
}
QColor TestClass::getColor(const QString &aName) const
{
return mColors.value(aName);
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
#include "testclass.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TestClass testClass;
testClass.setColor("entry1Color", Qt::green);
qDebug() << testClass.getColor("entry1Color");
return a.exec();
}
But also, it can be useful to check for how QMap works and which limitations for pairs it has.
When you are using QObject::setProperty on instance of QObject, it will be saved internally in QObject instance.
#Dmitriy: Thanks for clarification and the example code.
Now I do can read the value set by setProperty, fine so far.
But this is not all I want. I'd like to have some kind of a set function that will be called by the dynamic property setter, like the WRITE fn declaration for static Q_PROPERTY entries.
In my case, I create a dynamic property by calling setProperty("entry1Color") just in time with mColors.insert call.
The value should be written directly in my map["entry1Color"]. I did not yet stumble upon any idea to achieve this.

Is it possible to connect a slot or regular function from one class to a slot or regular function from another class? (QT)

To be specific to my problem I've been trying to connect a a slot from one class to a regular function of another class. I'm trying to do this so I can close the ui of one the main window from a dialog window. I tried everything I could possibly think of but it seems like every time I think of something to try the Qt compiler shuts me down by throwing some error or not working for no apparent reason such as when I did this
function(Ui::MainWindow *ui)
{
copy = ui; // copy is a pointer declared as Ui::MainWindow *copy in the dialog class
}
I tried this so I could close the main window from the copy pointer in the dialog class and although it compiled for that, it wouldn't compile when I tried to use it in another function of that class even though it was a class variable. After that I then realized that I should be able to connect the two functions from the main function. I wrote this
QObject::connect(&i, SIGNAL(on_passInput_returnPressed()), &w, SLOT(initalizer()));
The above compiles but when debugging I discovered it never gets executed and not sure why despite the fact that the SIGNAL on_passInput_returnPressed() is actually declared as slot in the class header. If that is the reason why it doesn't get executed how do I connect the slot from the dialog class to a regular function from the MainWindow class? There must be a way because I spent a day practically thinking about this non-stop and can't think of any other way given the nature of object scopes (in OOP) on top of the fact that the pointer thing I thought of didn't work.
Also I just now recreated the error from the pointer thing described above here it is.
error: invalid use of incomplete type 'class Ui::MainWindow'
copy->close();
^
Again this error is referring to trying to access the close function via the copy pointer from another function in the same class as the pointer assignment that worked in the other function. The copy pointer is declared as follows in the class header. Also in case you're wondering, yes, the pointer assignment written above does get executed. I checked via debugging.
private:
Ui::InitalPrompt *ui;
Ui::MainWindow *copy;
If you need more info just let me know what you need and I'll edit this post with it. I've obsessively tried so much I can think so much so that I've given up without further help due to how unforgiving Qt has been with me.
Also if there's a way of doing what I'm trying to do with the new Qt5 syntax of the connect function can you please give me the exact thing to type because despite looking into that new syntax myself I can't get it to compile for the life of me. (and yes I'm using Qt5) That's why the code above is written as old-fashion syntax.
Added the following as suggested to do so in a reply which is the class of the copy pointer.
#include "initalprompt.h"
#include "ui_initalprompt.h"
#include "mainwindow.h"
#include <QLineEdit>
#include <QCloseEvent>
#include <QMessageBox>
InitalPrompt::InitalPrompt(QWidget *parent) :
QDialog(parent),
ui(new Ui::InitalPrompt)
{
ui->setupUi(this);
}
InitalPrompt::~InitalPrompt()
{
delete ui;
}
void InitalPrompt::on_passInput_returnPressed()
{
pass = ui->passInput->text();
}
void InitalPrompt::reject()
{
QMessageBox::StandardButton resBtn = QMessageBox::Yes;
bool changes = false;
if (changes) {
resBtn = QMessageBox::question( this, "APP_NAME",
tr("Are you sure?\n"),
QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes,
QMessageBox::Yes);
}
if (resBtn == QMessageBox::Yes) {
QDialog::reject();
}
// the only issue is with the statment below don't know why
copy->close();
}
void InitalPrompt::catcher(Ui::MainWindow *ui)
{
copy = ui;
}
"Invalid use of incomplete type" means the compiler does not (yet) have a definition for the class when it reaches that line. In the header file that contains your copy pointer, include a forward declaration above the class declaration (the file would look something liek this):
#ifndef BLAH_BLAH_H
#define BLAH_BLAH_H
/*All of your normal #includes here*/
namespace Ui {
class InitialPrompt;
class MainWindow; //Note the forward declaration here
}
#include "mainwindow.h"
class BlahBlah
{
/*Class stuff here*/
private:
Ui::InitalPrompt *ui;
Ui::MainWindow *copy;
};
#endif //BLAH_BLAH_H
If you post the entirety of your class file that has the *copy, we can look further into it.
No, it is not possible. You can either:
call w->initalizer() directly from on_passInput_returnPressed() or
define a signal signal_on_passInput_returnPressed() in your ui class and emit that signal from on_passInput_returnPressed(). Then
QObject::connect(&i, SIGNAL(signal_on_passInput_returnPressed()), &w, SLOT(initalizer()));
should work.
For example:
class Whatever :
public QObject {
Q_OBJECT
void on_passInput_returnPressed();
signals:
void signal_on_passInput_returnPressed();
};
void Whatever::on_passInput_returnPressed() {
emit signal_on_passInput_returnPressed();
}

Qt Creator and Qstring

I'm new to programming and using qt to create my own GUI. I'm trying to make a search bar one of my list view's but it keeps saying that there is no matching function to call... This may be a really stupid question. Here is my code.
void Widget::on_SearchBar_textChanged(const QString &arg1)
{
QString Input;
ui->Online->find(Input);
}
and the error
C:\Qt\Qt5.1.1\Tools\QtCreator\bin\CryptoCourier\widget.cpp:21: error: no matching function for call to 'QListWidget::find(QString&)'
ui->Online->find(Input);
here is the rest of my code as requested
Ok So here is the rest of my code. Not much but here.
#include "widget.h"
#include "ui_CryptoCC.h"
#include <QString>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_SearchBar_textChanged(const QString &arg1)
{
#include <string>
QString Input;
ui->Online->find(Input);
}
^
You have two major problems:
#include statements should go outside of functions, since they literally include an entire file exactly where you put them.
For QString, the file you want to include is probably called "QString".
Try something like this:
#include <QString>
/* the rest of your code, which you didn't include in your example */
void Widget::on_SearchBar_textChanged(const QString &arg1)
{
/* by the way, you're calling Online->find() with an empty string,
* did you mean to use `arg1` here? */
QString Input;
ui->Online->find(Input);
}
Beyond that, I'd need to know what ui and ui->Online are before I could give you advice about what functions you can call on them.