I'm trying to make use of interfaces in Qt/C++, but I keep getting a compile error which makes no sense to me, because I have implemented the virtual functions in the derived class. So I was hoping for some help :) Oh yeah, and the compile error is "cannot declare variable 'w' to be of abstract type 'Widget' because the following virtual functions are pure within 'Widget': startGame(), getBoard(), gameFinished().
Main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
ADTType.h
#ifndef ADTTYPE_H
#define ADTTYPE_H
class ADTType
{
public:
virtual void startGame() = 0;
virtual void getBoard() = 0;
virtual void gameFinished() = 0;
virtual ~ADTType() {}
};
Q_DECLARE_INTERFACE(ADTType, "ADTType")
#endif // ADTTYPE_H
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QSignalMapper>
#include <QHBoxLayout>
#include <QPushButton>
#include "ADTType.h"
class Widget : public QWidget,
public ADTType
{
Q_OBJECT
Q_INTERFACES(ADTType)
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
QHBoxLayout * mainLayout;
QPushButton * startButton;
QPushButton * buttons[10];
QSignalMapper * map;
};
#endif // WIDGET_H
Widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent)
{}
Widget::~Widget()
{}
void Widget::startGame() {
for (int i = 0; i < 10; i++) {
buttons[i]->setStyleSheet("QPushButton {background-color: normal}");
}
setButtons(true);
startButton->setDisabled(true);
}
void Widget::getBoard() {
bool * cells = game->getCells();
for (int i = 0; i < 10; i++) {
if (!cells[i]) {
buttons[i]->setStyleSheet("QPushButton {background-color: red}");
buttons[i]->setEnabled(false);
}
}
}
void Widget::gameFinished() {
int answer = game->getAnswer();
buttons[answer]->setStyleSheet("QPushButton {background-color: green}");
setButtons(false);
game->reset();
QMessageBox::information(this,tr("Finito"),tr("You found it."),
QMessageBox::Ok);
startButton->setEnabled(true);
}
class Widget : public QWidget,
public ADTType
So Widget inherits from the abstract class ADTType. However, you don't declare the overrides (startGame() etc) in your Widget class, but you only define them in the Widget.cpp file. You also need to declare them in the Widget.h class header
// need these declarations inside the class Widget in Widget.h
virtual void startGame();
virtual void getBoard();
virtual void gameFinished();
Minimal example here.
You derived ADTType abstract class from the Widget so you need to override pure virtual functions in the Widget class otherwise it also will become abstract.
class Widget : public QWidget,
public ADTType
{
...
void startGame() { ... }
void getBoard() { ... }
void gameFinished() { ... }
};
Related
I am trying to access the member of a class declared in another class as an attribute.
The project class has a workArea that is also a class defined in the project.h.
I instanciate a project in the main, and then I send it to the mainWindow through its constructor. Once in the mainWindow constructor I try to access project->lat that works fine, but project->workArea->latInf crashes.
Any help will be highly appreciated.
project.h
#ifndef PROJECT_H
#define PROJECT_H
#include <QObject>
class WorkArea{
public://attributes
int latInf = 30;
public://methods
WorkArea()//Default constructor
{
}
~WorkArea();
};
class Project : public QObject
{
Q_OBJECT
public: //attributes
int lat = 20;
WorkArea* workArea;
public: //methods
explicit Project(QObject *parent = nullptr);
signals:
public slots:
};
#endif // PROJECT_H
main.cpp
#include "ui/mainwindow.h"
#include <QApplication>
#include "project.h"
int main(int argc, char *argv[])
{
Project* pj;
QApplication app(argc, argv);
MainWindow w( 0 , pj);
w.show();
return app.exec();
}
mainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent, Project *project) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
try
{
qDebug() << "Project latInf" << project->lat << "\n"; // works fine
qDebug()<< "Project lowLeft: " << project->workArea->latInf << "\n" ; // crashes
}
catch(std::exception &ex)
{
qDebug() << ex.what() ;
}
catch (...)
{
}
}
That was it. Thanks #eyllanesc. I forgot to create workArea. I though just instanciting it as an attribute in Project was fine, but I had to fill that memory space in the constructor of project.
project.h
#ifndef PROJECT_H
#define PROJECT_H
#include <QObject>
class WorkArea{
public://attributes
int latInf = 30;
public://methods
WorkArea()//Default constructor
{
}
~WorkArea();
};
class Project : public QObject
{
Q_OBJECT
public: //attributes
int lat = 20;
WorkArea* workArea;
public: //methods
explicit Project(QObject *parent = nullptr){
workArea = new WorkArea;
}
signals:
public slots:
};
#endif // PROJECT_H
I want to call a function when a button click. the implementation of the button is in the abstract class. but when I compile I'm getting this error.
This is my .h file of the base class
#ifndef HOME_H
#define HOME_H
#include<QGraphicsScene>
#include <QGraphicsScene>
#include<QPushButton>
class home
{
Q_OBJECT
public:
home();
virtual void set_home_background()=0 ;
QGraphicsScene *scene3;
QPushButton *button3;
private slots:
virtual void startgame1();
};
#endif // HOME_H
This is the base class
#include "home.h"
#include<QGraphicsScene>
#include<QGraphicsProxyWidget>
#include "QMessageBox"
home::home()
{
}
void home::set_home_background()
{
button3 = new QPushButton;
QObject::connect(button3,SIGNAL(clicked()),this,SLOT(startgame1()));
QGraphicsProxyWidget *proxy = this->scene3->addWidget(button3);
button3->setAutoFillBackground(true);
button3->setIcon(QIcon(":/Images/ng.png"));
button3->setIconSize(QSize(131,41));
proxy->setPos(130,430);
scene3->addItem(proxy);
}
void home::startgame1()
{
QMessageBox q;
q.setText("");
q.exec();
}
I'm getting this error
C:\Users\User\Documents\breakout_final\home.cpp:16: error: no matching
function for call to 'QObject::connect(QPushButton*&, const char*,
home*, const char*)'
QObject::connect(button3,SIGNAL(clicked()),this,SLOT(startgame1()));
^
You have an error in your code: in order to use Qt signals and slots, you should inherit your class from QObject, Q_OBJECT declaration itself is not enough:
#include <QObject>
class home : public QObject
{
Q_OBJECT
public:
home();
virtual void set_home_background()=0 ;
QGraphicsScene *scene3;
QPushButton *button3;
private slots:
virtual void startgame1();
};
In my application im having three widgets named as "Widget" , "one" and "two" . i tried to create the objects of the widget in main function as pass it as an argument to another widgets . it compiles successfully but application crashed before running , refer my code below and guide me,
//main.cpp
#include <QtGui/QApplication>
#include "widget.h"
#include "one.h"
#include "two.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget *w;
One *one;
Two *two;
w->GetObject(one,two);
one->GetObject(w,two);
two->GetObject(one,w);
w->show();
return a.exec();
}
//widget.cpp
#include "widget.h"
Widget::Widget(QWidget *parent) :QWidget(parent)
{
setupUi(this);
}
void Widget::GetObject(One *onee, Two *twoo)
{
one=onee;
two=twoo;
}
//widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include "ui_widget.h"
class One;
class Two;
class Widget : public QWidget, private Ui::Widget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
One *one;
Two *two;
void GetObject(One *onee, Two *twoo);
};
#endif // WIDGET_H
//one.cpp
#include "one.h"
One::One(QWidget *parent) :QWidget(parent)
{
setupUi(this);
}
void One::GetObject(Widget *widgett, Two *twoo)
{
widget = widgett;
two = twoo;
}
void One::on_pushButton_clicked()
{
widget->show();
}
//one.h
#ifndef ONE_H
#define ONE_H
#include "ui_one.h"
class Widget;
class Two;
class One : public QWidget, private Ui::One
{
Q_OBJECT
public:
explicit One(QWidget *parent = 0);
Widget *widget;
Two *two;
void GetObject(Widget *widgett, Two *twoo);
private slots:
void on_pushButton_clicked();
};
#endif // ONE_H
I am trying to create QQuickWidget based application.
What i am trying to do:
Class A(game.h) and Class B(gamestate.h) are forward declared. Class A is main QQuickWidget class with methods. Class B QObject derived class contains signals, slots, variables and methods.
Class B Variable values can set from class A -- Working
When variable value changes signal should be emitted -- working
when signal was emitted slot method should be called in class B -- working
Class B should invoke a method in class A -- working
Class A should create another qquickwidget -- NOT WORKING
(No compiling error. Application crashes on load)
I tried to call from class A and showIntro() function working fine. But when tried to call from class B its not working.
Game.h
#ifndef GAME_H
#define GAME_H
#include <QQuickWidget>
class GameState;
class Game: public QQuickWidget
{
Q_OBJECT
public:
Game();
GameState *gameState;
void showIntro();
public slots:
void onStatusChanged(QQuickWidget::Status);
};
#endif // GAME_H
Game.cpp
#include "game.h"
#include <QQuickWidget>
#include <QDebug>
#include "gamestate.h"
Game::Game(): QQuickWidget()
{
gameState = new GameState(this);
mainScreen = new QQuickWidget();
connect(this, SIGNAL(statusChanged(QQuickWidget::Status)), this, SLOT(onStatusChanged(QQuickWidget::Status)));
setFixedSize(450, 710);
setSource(QUrl("qrc:/EmptyScreen.qml"));
}
void Game::onStatusChanged(QQuickWidget::Status status)
{
switch(status)
{
case QQuickWidget::Ready:
qDebug() << "hi";
gameState->setValue(1);
//showIntro();
break;
case QQuickWidget::Error:
qDebug() << "Error";
break;
}
}
void Game::showIntro()
{
mainScreen->setSource(QUrl("qrc:/MainScreen.qml"));
mainScreen->setAttribute(Qt::WA_TranslucentBackground);
mainScreen->setParent(this);
}
Here is my Gamestate.h
#ifndef GAMESTATE_H
#define GAMESTATE_H
#include <QObject>
class Game;
class GameState : public QObject
{
Q_OBJECT
public:
explicit GameState(QObject *parent = 0);
int value() const {return m_value; }
Game *game;
signals:
void valueChanged(int newValue);
public slots:
void setValue(int value);
void stateChanged(int value);
private:
int m_value;
};
#endif // GAMESTATE_H
GameState.cpp
#include "gamestate.h"
#include "game.h"
GameState::GameState(QObject *parent) : QObject(parent)
{
m_value = 0;
connect(this,SIGNAL(valueChanged(int)), this, SLOT(stateChanged(int)));
}
void GameState::setValue(int value)
{
if(value != m_value)
{
m_value = value;
emit valueChanged(value);
}
}
void GameState::stateChanged(int value)
{
if(value == 1)
{
game->showIntro();
}
}
and my final main.cpp
#include <QApplication>
#include <QQmlApplicationEngine>
#include "game.h"
Game *game;
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
game = new Game();
game->show();
return app.exec();
}
Pls suggest me what could be the issue.
Member variable Game* game of class GameState is not initialized and therefore the program crashes when trying to dereference the pointer within GameState::stateChanged().
Change the constructor of GameState to the following:
// in gamestate.h
explicit GameState(Game *parent = 0);
// in gamestate.cpp
GameState::GameState(Game *parent) : QObject(parent), game(parent)
{
m_value = 0;
connect(this,SIGNAL(valueChanged(int)), this, SLOT(stateChanged(int)));
}
I want to write an application which consists of several plugins. My idea is that the plugin itself is always just a factory which then can create the required object.
So I created an Interface for the pluginfactory called AbstractFactoryPlugin with a pure virtual method called create. Because of the fact that I want to have several different plugins (factories) with the same interface I can’t put the Q_DECLARE_INTERFACE macro in the AbstractFactoryPlugin header file.
So for a sample plugin I created an Interface which inherits from AbstractFactoryPlugin called IMyObjectFactoryPlugin and declared this interface with the DECLARE macro. Further the MyObjectFactoryPlugin then inherits from QObject and IMyObjectFactoryPlugin.
But when I load the plugin and call the create function, the create function of MyObjectFactoryPlugin seems to be never called. What am I doing wrong?
Many thanx in advance.
Sourcecode:
#ifndef ABSTRACTPLUGINFACTORY_H
#define ABSTRACTPLUGINFACTORY_H
#include "IAnObject.h"
class AbstractFactoryPlugin
{
public:
virtual ~AbstractFactoryPlugin() {}
virtual IAnObject *create(QObject *parent) = 0;
};
#endif // ABSTRACTPLUGINFACTORY_H
#ifndef IMYOBJECTFACTORYPLUGIN_H
#define IMYOBJECTFACTORYPLUGIN_H
#include "AbstractFactoryPlugin.h"
#include <QtPlugin>
class IMyObjectFactoryPlugin : public AbstractFactoryPlugin
{
public:
virtual ~IMyObjectFactoryPlugin() {}
};
QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(IMyObjectFactoryPlugin,
"org.MyObjectFactoryPlugin");
QT_END_NAMESPACE
#endif // IMYOBJECTFACTORYPLUGIN_H
#ifndef MYOBJECTPLUGIN_H
#define MYOBJECTPLUGIN_H
#include <QtPlugin>
#include "IMyObjectFactoryPlugin.h"
#include "AbstractFactoryPlugin.h"
class MyObjectFactoryPlugin : public QObject, IMyObjectFactoryPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.MyObjectFactoryPlugin" )
Q_INTERFACES(IMyObjectFactoryPlugin)
public:
MyObjectFactoryPlugin(QObject *parent = 0);
IAnObject *create(QObject *parent);
};
#endif // MYOBJECTPLUGIN_H
#include "MyObject.h"
#include "MyObjectFactoryPlugin.h"
#include <QDebug>
MyObjectFactoryPlugin::MyObjectFactoryPlugin(QObject *parent) :
QObject(parent)
{
}
IAnObject *MyObjectFactoryPlugin::create(QObject *parent)
{
qDebug() << Q_FUNC_INFO << "was called";
return new MyObject();
}
#ifndef IANOBJECT_H
#define IANOBJECT_H
class IAnObject
{
public:
IAnObject() {isInitialized = false;}
virtual ~IAnObject() {}
virtual bool initialize() = 0;
protected:
bool isInitialized;
};
#endif // IANOBJECT_H
#include "IAnObject.h"
#ifndef MYOBJECT_H
#define MYOBJECT_H
class MyObject : public IAnObject
{
public:
MyObject();
bool initialize();
};
#endif // MYOBJECT_H
#include "MyObject.h"
MyObject::MyObject()
{
}
bool MyObject::initialize()
{
return true;
}
#include <QCoreApplication>
#include <QDir>
#include <QPluginLoader>
#include <QDebug>
#include <E:/QtProjects/_test_PlugIn/MyPlugin/AbstractFactoryPlugin.h>
#include <E:/QtProjects/_test_PlugIn/MyPlugin/IAnObject.h>
#include <E:/QtProjects/_test_PlugIn/MyPlugin/IMyObjectFactoryPlugin.h>
IAnObject *loadPlugin()
{
QDir dir(QCoreApplication::applicationDirPath());
qDebug() << dir;
foreach(QString fileName, dir.entryList(QDir::Files))
{
QPluginLoader pluginLoader(dir.absoluteFilePath(fileName));
QObject *plugin = pluginLoader.instance();
qDebug() << fileName;
if(plugin)
{
qDebug() << "##### Plugin load ok #####";
AbstractFactoryPlugin *abstractFactoryPlugin = reinterpret_cast<AbstractFactoryPlugin *>(plugin);
return abstractFactoryPlugin->create(NULL);
}
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << "loadPlugin:" << loadPlugin();
return a.exec();
}
Any Qt5 plugin must inherit from QObject, if you want your base class to be independent from QObject you'll have to create an intermediary class that inherits both AbstractFactoryPlugin and QObject (let's call it AbstractMyObjectFactoryPlugin).
#ifndef ABSTRACTMYOBJECTFACTORYPLUGIN_H
#define ABSTRACTMYOBJECTFACTORYPLUGIN_H
#include "AbstractFactoryPlugin.h"
class AbstractMyObjectFactoryPlugin : public QObject, public AbstractFactoryPlugin
{
Q_OBJECT
public:
AbstractMyObjectFactoryPlugin(QObject *parent = 0) : QObject(parent) { }
virtual ~AbstractMyObjectFactoryPlugin() { }
};
Q_DECLARE_INTERFACE(AbstractMyObjectFactoryPlugin,
"org.AbstractFactoryPlugin");
#endif // ABSTRACTMYOBJECTFACTORYPLUGIN_H
To create a plugin, you'll have to inherit from this class and override the create() method:
class MyObjectFactoryPlugin : public AbstractMyObjectFactoryPlugin
{
Q_OBJECT
Q_INTERFACES(AbstractMyObjectFactoryPlugin)
Q_PLUGIN_METADATA(IID "org.MyObjectFactoryPlugin" FILE "MyObjectFactoryPlugin.json")
public:
MyObjectFactoryPlugin(QObject* parent = 0) : AbstractMyObjectFactoryPlugin(parent) { }
virtual IAnObject *create(QObject *parent);
virtual ~MyObjectFactoryPlugin() { }
};
To cast the loaded plugin (a QObject) to AbstractFactoryPlugin safetly, you'll have to cast it to the intermediary class first.
AbstractFactoryPlugin * objectFactoryPlugin = qobject_cast< AbstractMyObjectFactoryPlugin * >(plugin);
The implicit assignment will cast it to the right base class.
Note: You'll have to check if the cast is successful first if you have other inheritance trees.