could you take a look and explain, what am I doing wrong in code below?
#ifndef BACKEND_H
#define BACKEND_H
#include <QObject>
#include <QDebug>
#include <QtQml>
class BackEnd : public QObject
{
Q_OBJECT
Q_PROPERTY(int player READ player WRITE player_change)
QML_ELEMENT
int player;
public:
explicit BackEnd(QObject *parent = nullptr);
signals:
int player_changed(int player);
public slots:
int player_change(int player);
};
#endif // BACKEND_H
cpp:
#include "backend.h"
BackEnd::BackEnd(QObject *parent)
: QObject{parent}
{
}
int BackEnd::player_change(int player)
{
return (player == 1) ? 2 : 1;
}
Error:
Expression cannot be used as a function
Error appears in auto-edited moc file...
Removing Q_PROPERTY makes it fine...
The error says that the Q_PROPERTY macro can't use the member player as a function.
A READ accessor function is required if no MEMBER variable was
specified. It is for reading the property value. Ideally, a const
function is used for this purpose, and it must return either the
property's type or a const reference to that type. e.g.,
QWidget::focus is a read-only property with READ function,
QWidget::hasFocus().
You need to create a getter and use it as the READ function. Or you use MEMBER.
A MEMBER variable association is required if no READ accessor function
is specified. This makes the given member variable readable and
writable without the need of creating READ and WRITE accessor
functions. It's still possible to use READ or WRITE accessor functions
in addition to MEMBER variable association (but not both), if you need
to control the variable access.
Have a look here.
#ifndef BACKEND_H
#define BACKEND_H
#include <QDebug>
#include <QObject>
#include <QtQml>
class BackEnd : public QObject
{
Q_OBJECT
Q_PROPERTY(int foo READ foo WRITE setFoo NOTIFY fooChanged)
Q_PROPERTY(int bar MEMBER bar NOTIFY barChanged)
QML_ELEMENT
public:
explicit BackEnd(QObject *parent = nullptr) : QObject{parent} {}
int foo() const { return m_foo; }
void setFoo(int val) { m_foo = val; emit fooChanged(); }
signals:
void fooChanged();
void barChanged();
private:
int m_foo;
int bar;
};
#endif // BACKEND_H
Related
I'm writing a RSS Feed Reader in Qt. My approach is to save every Feed in an object of the class Feed. The download is handled inside the Feed class, therefore I need to make sure that every object of Feed can access the (one) NetworkAccessManager. To manage this (and to make sure the NetworkAccessManager has only one instance) I want to make a Singleton injection. The problem is, with my current code I get the following error message
...main.cpp:-1: Fehler: undefined reference to `NetworkMgr::qnam'
Following is the code of which I think it is the most relevant for the problem, if you need anything more let me know.
I try to get the pointer on the instance of the NetworkAccessManager directly inside the constructor of the Feed class and then safe it in a private variable.
#ifndef FEED_H
#define FEED_H
#include <QObject>
#include <QGuiApplication>
#include <QtQuick>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QPixmap>
#include <iostream>
#include <QDomDocument>
#include "NetworkMgr.h"
using namespace std;
class Feed : public QObject {
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged)
Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged)
Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
public:
Feed(QObject* parent = NULL) : QObject(parent){
m_nMgr = NetworkMgr::getInstance();
connect(m_nMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(parse(QNetworkReply*)));
m_active = false;
};
QString name();
void setName(QString);
QString url();
void setUrl(QString);
int id();
void setId(int);
bool active();
void setActive(bool);
public slots:
void get();
private:
QString m_name;
QString m_url;
int m_id;
bool m_active;
QNetworkAccessManager* m_nMgr;
private slots:
void parse(QNetworkReply* reply);
signals:
void nameChanged();
void urlChanged();
void idChanged();
void activeChanged();
};
#endif
This is my Singleton class:
#ifndef NETWORKMGR_H
#define NETWORKMGR_H
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
class NetworkMgr : public QObject {
Q_OBJECT
NetworkMgr(QObject* parent = NULL) : QObject(parent){};
~NetworkMgr(){
delete qnam;
}
static QNetworkAccessManager* qnam;
public:
static QNetworkAccessManager* getInstance(){
if(qnam == NULL){
qnam = new QNetworkAccessManager();
}
return qnam;
}
NetworkMgr(NetworkMgr const& copy) = delete;
NetworkMgr& operator=(NetworkMgr const& copy) = delete;
};
//QNetworkAccessManager* NetworkMgr::qnam = NULL;
#endif
As you can see, I also tried to initialize qnam to nullpointer, but then I get the error:
...Feed.h:17: Fehler: multiple definition of NetworkMgr::qnam' debug/main.o: In function Feed::~Feed()':
...Feed.h:17: multiple definition of `NetworkMgr::qnam'
And this is how I tried to call it as a test from main.cpp:
Feed feed;
feed.setUrl("https://www.deskmodder.de/blog/feed/");
feed.get();
I tried getting the instance of NetworkAccessManager outside the constructor as well, but the error stays the same.
I would really appreciate it, if anybody here has an idea what I could try to get rid of this error.. Before I take a completely different approach, I'd like to try it this way.
Thanks in advance to anyone contributing to fix my problem!
I am new in C++ Qt and struggling with the correct use of forward declarations and #include.
What I want to do:
I have a Qt Gui (Class Ui::Gui) where we can set values.
I want to save these values in Gui Class variables.
As soon as a button (Generate Xml) is clicked, I want to pass the object
'ui' to the XmlGeneratorClass, So i can use the values to generate a Xml.
gui.h
#ifndef GUI_H
#define GUI_H
#include <QMainWindow>
#include <QDebug>
#include "xmlgeneratorqobject.h"
namespace Ui {
class Gui;
}
class Gui : public QMainWindow
{
Q_OBJECT
public:
explicit Gui(QWidget *parent = nullptr);
~Gui();
qint8 testvalue = 1;
signals:
void transmitToXmlGen(Ui::Gui*);
private slots:
void on_pushButtonGenerateXml_clicked();
private:
Ui::Gui *ui;
XmlGeneratorQObject *xmlgenerator = new XmlGeneratorQObject();
};
#endif // GUI_H
gui.cpp
#include "gui.h"
#include "ui_gui.h"
Gui::Gui(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Gui)
{
ui->setupUi(this);
connect(this,SIGNAL(transmitToXmlGen(Ui::Gui*)),xmlgenerator,SLOT(receiveFromGui(Ui::Gui*)));
}
Gui::~Gui()
{
delete ui;
}
void Gui::on_pushButtonGenerateXml_clicked()
{
emit transmitToXmlGen(ui);
}
xmlgeneratorqobject.h
#ifndef XMLGENERATORQOBJECT_H
#define XMLGENERATORQOBJECT_H
#include <QObject>
#include <QDebug>
namespace Ui {
class XmlGeneratorQObject;
class Gui;
}
class XmlGeneratorQObject : public QObject {
Q_OBJECT
public:
explicit XmlGeneratorQObject(QObject * parent = nullptr);
private slots:
void receiveFromGui(Ui::Gui*);
};
#endif // XMLGENERATORQOBJECT_H
xmlgeneratorqobject.cpp
#include "xmlgeneratorqobject.h"
XmlGeneratorQObject::XmlGeneratorQObject(QObject *parent){}
void XmlGeneratorQObject::receiveFromGui(Ui::Gui* objectFromGui)
{
qDebug() << objectFromGui->testvalue; // ERROR member access into incomplete type 'Ui::Gui'
}
Expected result:
Access to public variables from passed gui-object should be possible
Actual result:
member access into incomplete type 'Ui::Gui'
Can you please help me learn forward declaration / include?
Is my approach in general okay?
Your xmlgeneratorqobject.cpp needs the line
#include "ui_gui.h"
This gives it the details of the ui widgets. This file is generated by the Qt build system.
So I I have an h file and a cpp file in a Qt project. I have to declare some qstrings inside my header file and I would like to reference them in my cpp file but I don't seem to be able to access it, can someone explain why or the correct way to do it?
#ifndef PROFILE_H
#define PROFILE_H
#include <QMainWindow>
#include "login.h"
#include "searchnote.h"
#include "note.h"
#include <QDebug>
namespace Ui {
class Profile;
}
class Profile : public QMainWindow
{
Q_OBJECT
public:
explicit Profile(QWidget *parent = 0);
~Profile();
private slots:
void on_actionAdd_Note_triggered();
private:
Ui::Profile *ui;
private:
QString name;
QString major;
QString school;
Note myNoteList;
};
#endif // PROFILE_H
#include "profile.h"
#include "ui_profile.h"
Profile::Profile(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Profile)
{
ui->setupUi(this);
}
Profile::~Profile()
{
delete ui;
}
void Profile::on_actionAdd_Note_triggered()
{
SearchNote openSearch; //will send us the searchNote gui
openSearch.setModal(true);
openSearch.exec();
}
void myNoteListAdd(QString newName){
myNoteList.add(); //the cpp file doesnt recognize this object
}
myNoteListAdd is a stand-alone function, myNoteList is a private data member of Profile class.
Only member functions (often also called methods) of the same class can access these private data members
It may be the case that you intend myNoteListAdd to be a member function of Profile, i.e.
class Profile : public QMainWindow
{
Q_OBJECT
public:
explicit Profile(QWidget *parent = 0);
~Profile();
private slots:
void on_actionAdd_Note_triggered();
**void myNoteListAdd(QString newName);**
private:
Ui::Profile *ui;
private:
QString name;
QString major;
QString school;
Note myNoteList;
};
And implement as:
void Profile::myNoteListAdd(QString newName){
myNoteList.add(newName); // assuming you want to add newName to myNoteList
}
Otherwise, you need some form of accessing the member myNoteList, either by making it public or having a getter member. In either case you need an instance of a Profile to work with, i.e.:
class Profile : public QMainWindow
{
Q_OBJECT
public:
explicit Profile(QWidget *parent = 0);
~Profile();
//either this:
Note myPublicNoteList;
// or this
Note getNoteList() { return myNoteList; }
private slots:
void on_actionAdd_Note_triggered();
private:
Ui::Profile *ui;
private:
QString name;
QString major;
QString school;
};
then in your .cpp
void myNoteListAdd(QString newName)
{
Profile p = new Profile(); // or some other mechanism to get a Profile
//then either
p.myPublicNoteList.add(newName);
// or
p->getNoteList().add(newName);
}
I have two classes: AbstractClass and SubClass.
This is basically my code (well, just some example code):
abstractclass.h
class AbstractClass
{
public:
AbstractClass();
void doSomething();
protected:
virtual void implementMe() = 0;
int a;
};
abstractclass.cpp
#include "abstractclass.h"
AbstractClass::AbstractClass(){}
void AbstractClass::doSomething()
{
implementMe(); // compiler error: "implementMe() was not declared in this scope"
a = 0; // same compiler error here...
}
subclass.h
#include "abstractclass.h"
class SubClass : public AbstractClass
{
public:
SubClass();
protected:
void implementMe();
};
subclass.cpp
#include "subclass.h"
SubClass::SubClass() {}
void SubClass::implementMe()
{
// do some stuff
}
In the AbstractClass, however, I keep getting a compiler error (for the virtual function as well as for the class variable):
implementMe() was not declared in this scope
The only way I found to get rid of this was to use forward-declaration:
void implementMe();
AbstractClass::doSomething()
{
implementMe();
}
I cannot believe that this is the correct way, though?
Thanks!
EDIT:
Ok, as my conceptual understanding of subclassing in C++ doesn't seem to be totally wrong (see the comments), I'm gonna share some of my original source code. Hopefully this will help to indentify the error.
This is my abstract / base class:
abstractenvironment.h
#ifndef ABSTRACTENVIRONMENT_H
#define ABSTRACTENVIRONMENT_H
#include <QObject>
class AbstractEnvironment : public QObject
{
Q_OBJECT
public:
AbstractEnvironment(QObject *parent = 0);
protected:
virtual void process() = 0;
quint32 counter;
private slots:
void handleTimeout();
};
#endif // ABSTRACTENVIRONMENT_H
abstractenvironment.cpp
#include "abstractenvironment.h"
#include <QTimer>
QTimer *myTimer;
AbstractEnvironment::AbstractEnvironment(QObject *parent) :
QObject(parent)
{
myTimer = new QTimer(this);
connect(myTimer, &QTimer::timeout, this, &AbstractEnvironment::handleTimeout);
myTimer->start(1);
counter = 0;
}
void handleTimeout()
{
process();
counter++;
}
And this is my subclass:
environment.h
#ifndef ENVIRONMENT_H
#define ENVIRONMENT_H
#include "abstractenvironment.h"
class Environment : public AbstractEnvironment
{
Q_OBJECT
public:
Environment(Controller *controller, QObject *parent = 0);
protected:
void process();
};
#endif // ENVIRONMENT_H
environment.cpp
#include "environment.h"
Environment::Environment(Controller *controller, QObject *parent) :
AbstractEnvironment(controller, parent) {}
void Environment::process()
{
// do something
}
PS: I've learned from the first part of this question and tried to compile the source code above inside Qt with MinGW. I get exactly two error messages (as expected):
..\untitled\abstractenvironment.cpp: In function 'void handleTimeout()':
..\untitled\abstractenvironment.cpp:17:13: error: 'process' was not declared in this scope
..\untitled\abstractenvironment.cpp:18:5: error: 'counter' was not declared in this scope
In case you want to try it yourself, I've zipped the Qt project and uploaded it to my Dropbox (of course I will remove this file at some point but the code is exactly the same as in the post above --> it's just for the sake of convenience, so you don't have to copy-paste it yourself)
EDIT: You just changed your question. So I can't tell if your original text was your actual source code or not. Good rule of thumb, paste your actual code rather than paraphrase it (then de-identify or reduce it if needed).
ORIGINAL ANSWER:
implementMe(); // compiler error: "implementMe() was not declared in this scope"
That is because doSomething() isn't declared properly in AbstractClass. You "declared" it in the base class with:
doSomething();
The compiler doesn't recognize AbstractClass::doSomething() out of line definition so nothing inside the implementation is resolved to the class scope.
Change that to:
void doSomething();
just like in your derived class.
and
AbstractClass::doSomething()
{
implementMe();
}
to
void AbstractClass::doSomething()
{
implementMe();
}
UPDATE:
void handleTimeout()
{
process();
counter++;
}
is a global function. That isn't the class implementation. It should be:
void AbstractClass::handleTimeout()
{
process();
counter++;
}
In abstractenvironment.cpp you define void handleTimeout(), which is non-member function and does not relate to AbstractEnvironment class. Thus, it doesn't look for AbstractEnvironment::process() and AbstractEnvironment::counter, but for ::process() and ::counter instead (which are not declared, hence the error).
Change it to void AbstractEnvironment::handleTimeout() and it should compile.
I am new to c++ and I have the following code in VS2010 using Qt:
// test.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_test.h"
#include "testDevice.h"
#include "testControl.h"
class test : public QMainWindow
{
Q_OBJECT
public:
test(QWidget *parent = 0) : control(device,0) {}
~test();
private:
Ui::testClass ui;
testDevice device;
testControl control;
};
// test.cpp
#include "test.h"
test::test(QWidget *parent) : QMainWindow(parent)
{
ui.setupUi(this);
device.start();
control.start();
}
test::~test()
{
}
// testControl.h
#pragma once
#include <QThread>
#include "testDevice.h"
class testControl : public QThread
{
Q_OBJECT
public:
testControl(testDevice& device, QObject *parent = 0);
protected:
void run(void);
private:
testDevice device;
~testControl(void);
};
// testControl.cpp
#include "testControl.h"
testControl::testControl(testDevice& thisDevice, QObject *parent) : QThread(parent)
{
}
void testControl::run(void)
{
}
testControl::~testControl(void)
{
}
VS2010 is saying "no appropriate default constructor available" and it marks:
test::test(QWidget *parent) : QMainWindow(parent)
{
and
test::~test()
as the error source. I have tried to use testControl as a pointer and as a reference but I got many other errors...could someone please help me out with this one and explain to me whats going on?
You are providing an implicitly inline definition of test's constructor in the test class definition in the header:
test(QWidget *parent = 0) : control(device,0) {}
This is most likely what the compiler is complaining about. Besides that, you go on to provide a different definition in the .cpp file. You can only have one definition.
There are two ways to fix this.
1) implicitly inline definition of the constructor in the class definition. Modify your existing header code to call the appropriate QMainWindow constructor in the initialization list. And remove the constructor definition from the .cpp file:
// in test.h
test(QWidget* parent = 0) : QMainWindow(parent), control(device, 0)
{
ui.setupUi(this);
device.start();
control.start();
}
2) Declare the constructor in the header, and define it in the .cpp:
// in test.h
test(QWidget* parent = 0); // declaration, no definition
// in test.cpp
test::test(QWidget* parent = 0) : QMainWindow(parent), control(device, 0)
{
ui.setupUi(this);
device.start();
control.start();
}
Either of these solutions should work. What you can't have is a combination of the two, which is what your code sample exhibits.
You may also need a definition of test::~test(). In your code sample you only show a declaration.
You have two major issues ongoing:
1) You should probably write this constructor leaving the definition for the constructor in the header behind.
You ran into the trap of two definitions provided, one in the header, and the other in the source file.
You either need to have the declaration in the header, and definition in the source, or the declaration and definition in the header. You cannot have one declaration and two definitions distributed in the header and source files!
You had the empty definition in the header by {} and the other definition with { .... } in the source file. How would the compiler know which one you really wanted? It cannot reliably... even if it picks up either version.
2) Also, your testControl destructor seems to be private. That is not a good idea. Change that destructor to public!
test.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_test.h"
#include "testDevice.h"
#include "testControl.h"
class test : public QMainWindow
{
Q_OBJECT
public:
// Only declare, do not define it here
// Also, for completeness: you should use the "explicit" keyword in here.
explicit test(QWidget *parent = 0);
~test();
private:
Ui::testClass ui;
testDevice device;
testControl control;
};
test.cpp
#include "test.h"
test::test(QWidget *parent = 0)
: QMainWindow(parent)
, control(device,0)
{
ui.setupUi(this);
device.start();
control.start();
}
test::~test()
{
}
testControl.h
#pragma once
#include <QThread>
#include "testDevice.h"
class testControl : public QThread
{
Q_OBJECT
public:
testControl(testDevice& device, QObject *parent = 0);
// Change this to being _public_ rather than _private_ as in your code.
~testControl(void);
protected:
void run(void);
private:
testDevice device;
};
When a class is constructed, all the data members are constructed as well. If there is a default constructor for a particular data member, that one is executed.
If you need to execute a specific non-default constructor, you must use the member initialisation list in order to construct that particular data member.
I suspect that your problem is with either your
testDevice device;
testControl control;
data members, or both.
What are the available constructors for both these classes? If there are no default constructors available, you must initialise them in the members' initialisation list, supplying appropriate parameter arguments.