I am working on an IDE written in QT. I need to use the QMainWindow AND the QSyntaxHighLighter classes. However, when compiling it spits out the following error.
cannot declare variable 'w' to be of abstract type 'SquareSDK'
That refers to my main.cpp file.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
SquareSDK w;
w.show();
return a.exec();
}
That class is defined in ediot.h
#ifndef EDIOT_H
#define EDIOT_H
#include <QMainWindow>
#include <QFileDialog>
#include <QtCore>
#include <QtGui>
#include <QObject>
#include <QSyntaxHighlighter>
namespace Ui {
class SquareSDK;
}
class SquareSDK : public QMainWindow, private QSyntaxHighlighter
{
Q_OBJECT
public:
explicit SquareSDK(QWidget *parent = 0);
~SquareSDK();
private slots:
void on_actionUndo_triggered();
void on_actionRedo_triggered();
void on_actionCut_triggered();
void on_actionCopy_triggered();
void on_actionPaste_triggered();
void on_actionNew_triggered();
void on_actionOpen_triggered();
void on_actionSave_triggered();
void on_actionSave_As_triggered();
void on_actionRun_in_Default_Web_Browser_triggered();
void on_actionReload_triggered();
void test();
void syntax();
private:
Ui::SquareSDK *ui;
QString mFilename;
QString urlname;
QString urldebug;
QString OS;
QString a;
QString b;
QString error;
QString ext;
QString text;
};
#endif // EDIOT_H
As one or both of base classes have 1 or more pure virtual methods, until you implement them in SquareSDK, SquareSDK is an abstract class (because it literally inherits those pure virtual methods). You can't instantiate an abstract class.
(Although you can use it as a type for pointer or reference. But it can only point to its non-abstract sub-classes, despite pointer-type being of abstract class. But that's not important right now)
I checked out the documentation for QSyntaxHighlighter, and it has 1 pure virtual method.
//this is how it looks like inside QSyntaxHighlighter class
virtual void highlightBlock (const QString& text) = 0;
So implement it in your SquareSDK:
//in .h
void highlightBlock (const QString& text);
//in .cpp
void SquareSDK::highlightBlock (const QString& text)
{
//...yourcode...
}
It's a function for highlighting blocks, and because it's pure virtual, it has absolutely no original behavior defined so you must program it completely on your own. So implement it in a way it highlights a block the way you want it highlighted.
QMainWindow, luckily, contains no pure virtual methods, which cuts you some slack.
EDIT:
Inherit QSyntaxHighlighter as public. highlightBlock is protected, and if base class is inherited as private, it becomes unreachable.
Double QObject inheritance is forbidden in Qt! So you can't do it with QMainWindow and QSyntaxHighlighter. In this case double inheritance is bad in many many other ways!
Use composition not aggregation here!
Related
I've been following a simple QT tutorial and came up with a weird noob question.
https://www.youtube.com/watch?v=F56fSKoNCtk&list=PLS1QulWo1RIZiBcTr5urECberTITj7gjA&index=5
this is the tutorial.
Here's the my_window.h
#ifndef MY_WINDOW_H
#define MY_WINDOW_H
#include <QMainWindow>
namespace Ui {
class MyWindow;
}
class MyWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MyWindow(QWidget *parent = nullptr);
~MyWindow();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::MyWindow *ui;
};
#endif // MY_WINDOW_H
and my_window.cpp.
#include "my_window.h"
#include "ui_mywindow.h"
MyWindow::MyWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MyWindow)
{
ui->setupUi(this);
connect(ui->horizontalSlider,SIGNAL(valueChanged(int)),
ui->progressBar,SLOT(setValue(int)));
}
MyWindow::~MyWindow()
{
delete ui;
}
void MyWindow::on_pushButton_clicked()
{
ui->label->setText("Clicked!");
}
void MyWindow::on_pushButton_2_clicked()
{
ui->label->setText("Why...?");
}
In my_window.cpp, the definition of the constructor,
it does the tasks via the member pointer, 'ui' which is a pointer of 'MyWindow type' instance.
I thought 'this' pointer is also a 'MyWindow' class type pointer so i thought i can access the horizontalSlider and progressBar with this pointer too.
But i couldn't.
what makes the difference between two of them?
Your class MyWindow that you define in my_window.h and implement in my_window.cpp is ::MyWindow. Then you have ::Ui::MyWindow which is a totally separate class, and is defined and implemented in auto-generated files by Qt and the Qt tools.
You can have many symbols with the same name, as long as they are defined in different scopes. These symbols can even be different types, like one could be a class, one could be a variable, one could be a function, etc.
In the main.cppi'm creating a singleton type of a class to use it in qml with the following function:
qmlRegisterSingletonType<DataloopWrapper>("com.xpto.connector", 1, 0, "DataloopWrapper",&DataloopWrapper::qmlInstance);
a bit down on the main.cpp i call a function of another object where i want to call a function from that singleton
maybe something like this qmlTranslator.loadLanguage(lang, DataloopWrapper::qmlInstance); is possible?
I'm declaring QmlTranslatorclass the following way:
#ifndef QMLTRANSLATOR_H
#define QMLTRANSLATOR_H
#include <QObject>
#include <QTranslator>
#include <QQmlEngine>
#include <QGuiApplication>
class QmlTranslator : public QObject
{
Q_OBJECT
public:
QmlTranslator(QQmlEngine *engine, QGuiApplication *app);
Q_INVOKABLE void selectLanguage(QString language);
void InstallTranslator();
void loadLanguage(QString language, QObject*(QQmlEngine*,QJSEngine*) objDataloop);
virtual ~QmlTranslator();
signals:
void languageChanged();
private:
QTranslator *_translator;
QQmlEngine *_engine;
QGuiApplication *_app;
};
#endif // QMLTRANSLATOR_H
I'm not finding a way to pass DataloopWrapper::qmlInstanceas argument. At least it gives error in void loadLanguage(QString language, QObject*(QQmlEngine*,QJSEngine*) objDataloop);on the qmlTranslator definition.
From a public: Members of DataloopWrapperi have the defenition of qmlInstance, it's this:
class DataloopWrapper : public QObject, public something::DataloopCBHandler,
public something::DataloopTransferCBHandler
{
Q_OBJECT
public:
explicit DataloopWrapper(QObject *parent = nullptr);
virtual ~DataloopWrapper();
static QObject *qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine)
{
Q_UNUSED(engine);
Q_UNUSED(scriptEngine);
return new DataloopWrapper;
}
DataloopWrapper::qmlInstance is a function, that you need to call in order to get a pointer to a QObject.
For for any function you want to pass this object, you need to make it accept a pointer to a QObject (type QObject*), and don't forget to call DataloopWrapper::qmlInstance.
Translated into code:
class QmlTranslator : public QObject
{
...
void loadLanguage(QString language, QObject* objDataloop);
...
};
...
qmlTranslator.loadLanguage(lang, DataloopWrapper::qmlInstance(aQMLEngineObjectPointer, aQJSEnginePointer));
Trying to add functionality to QString but get build errors ?? And if I am missing things??
#ifndef CSTRING_H
#define CSTRING_H
#include <QString>
#include <QStringList>
#include <QObject>
class CString : public QString, public QObject
{
Q_OBJECT
public:
explicit CString(QObject *parent = 0);
QStringList Find(QString qstrSearch);//all occurances
signals:
public slots:
};
#endif // CSTRING_H
#include "cstring.h"
CString::CString(QObject *parent) :
QString(parent) //ERROR IS POINTING TO HERE
{
}
QStringList Find(QString qstrSearch)//all occurances
{//indexOf, contains
QStringList qstrList;
return qstrList;
}
Don't derive classes form QString since it wasn't designed with polymorphy in mind (note that it has no virtual methods, in particular no virtual destructors) If you want to provide new utility functions, just use free functions - you may want to put them in a namespace:
namespace CString {
QStringList find(const QString &search);
}
QString(parent) Qstring does not have a constructor taking a QObject-parent as parameter. Therefor the compiler tries to cast your QObject to closest Matching constructor, which probably would be QString ( QChar ch )
You should use composition instead of inheritance here, because QString is not designed for subclassing. You can get a lot of troubles if you will subclass it.
Do something like this:
class CString : public QObject //if you're really need this class to be QObject, that's not always a good idea
{
Q_OBJECT
public:
explicit CString(QObject *parent = 0) :
QObject(parent),
mString() //QString have no constructors with parameter QObject*...
{
}
private:
QString mString;
}
Of course, implementation should be in cpp file, it's just a short example
I have a problem with accessing ui elements from another class(with instance). I have a second QMainWindow in my application, I can access in secondWindow.cxx class all ui elements but not in read.cxx class. My code looks like following. Where is my mistake? Thank you for your help.
-------------------------------secondWindow.h------------------------------------
#ifndef __secondWindow_h
#define __secondWindow_h
#include "ui_secondwindow.h"
class secondWindow : public QMainWindow
{
friend class read;
igstkStandardClassBasicTraitsMacro(secondWindow, QMainWindow);
Q_OBJECT
public:
igstkStateMachineMacro();
secondWindow();
virtual ~secondWindow();
void createSignalAndSlots();
public slots:
void secondWindowTest();
protected:
private:
Ui::secondMainWindow m_secondWindowUI;
};
#endif
-------------------------------secondWindow.cxx------------------------------------
#include "secondWindow.moc"
#include "secondWindow.h"
#include "read.h"
secondWindow::secondWindow() :m_StateMachine(this)
{
m_secondWindowUI.setupUi(this);
createSignalAndSlots();
}
void secondWindow::createSignalAndSlots()
{
connect(m_secondWindowUI.pushButton1, SIGNAL(clicked()),this, SLOT(secondWindowTest()));
connect(m_secondWindowUI.pushButton2, SIGNAL(clicked()), read::instance(), SLOT(readTest()));
}
void secondWindow::secondWindowTest()
{
m_secondWindowUI.pushButton1->setEnabled(true); //OK
}
secondWindow::~secondWindow(){}
---------------------------------read.h--------------------------------------
#pragma once
#include "secondWindow.h"
class read : public QObject
{
Q_OBJECT
public:
static read *instance();
read();
virtual ~read() {}
public slots:
void readTest();
protected:
secondWindow *m_readUI;
static read *m_read;
private:
};
---------------------------------read.cxx--------------------------------------
#include <read.moc>
#include "secondWindow.h"
#include "read.h"
read *read::m_read= NULL;
read::read()
{
m_readUI = dynamic_cast<secondWindow*>( QApplication::instance() );
}
read *read::instance()
{
if(m_read == NULL)
m_read = new read();
return m_read;
}
void read::readTest()
{
m_readUI->m_secondWindowUI.qlabelTest->setText("test"); //segmentation fault
}
You are casting a QApplication::instance(), which is a QApplication * deriving from QCoreApplication * deriving from QObject *. That won't work, it's not a secondWindow *, not even a QMainWindow *, not even a QWidget *.
Apart from that, your coding style is rather strange -- in Qt, it's customary to use CamelCase for classes, not thisStuff which usually applies to functions and methods. Including <read.moc> is just wrong. Why is read::m_read static? Finally, the coupling between the two window classes is set up in a strange way (accessing global stuff like QApplication just to get a reference to another window smells ugly code). A much better and more obvious approach is to either wrap all of your windows in a parent object or setting up the dependencies explicitly, perhaps like this:
MainWindow *mainWindow = new MainWindow();
SecondWindow *second = new SecondWindow(mainWindow);
UtilityWindow *utilityWin = new UtilityWindow(second);
I'm new in QT, and I'm just testing out the MOC.
For a given class:
class Counter : public QObject
{
Q_OBJECT
int m_value;
public:
Counter() {m_value = 0;}
~Counter() {}
int value() {return m_value;}
public slots:
void setValue(int value);
signals:
void valueChanged(int newValue);
};
I want to get a list of all methods in a class, but seem to only be getting a list of signals and slots, although the documentation says it should be all methods? Here's my code:
#include <QCoreApplication>
#include <QObject>
#include <QMetaMethod>
#include <iostream>
using std::cout;
using std::endl;
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
const QMetaObject cntmo = Counter::staticMetaObject;
for(int i = 0; i != cntmo.methodCount(); ++i)
{
QMetaMethod qmm(cntmo.method(i));
cout << qmm.signature() << endl;
}
return app.exec();
}
Please beware this is my best c/p, perhaps I forgot to include some headers.
My output:
destroyed(QObject*)
destroyed()
deleteLater()
_q_reregisterTimers(void*)
valueChanged(int)
setValue(int)
Does anyone know why this is happening? Does qt not recognise
int value() {return m_value;}
as a valid method? If so, is there a macro I've forgotten or something like that?
P.S. I'm using 4.6.2
UPDATE
I forgot the implementation of the setValue method, not that it makes too much a difference to my actual question.
void Counter::setValue(int value)
{
if(value != m_value)
{
m_value = value;
emit valueChanged(value);
}
}
As far as I remember you can't access all methods of a QObject subclass through the QMetaObject it provides access only for the signals, slots and INVOCABLE methods:
class MyClass: public QObject {
Q_OBJECT
public:
Q_INVOCABLE int someMethod(const QString &someParam);
};
Maybe it's also provide access to Q_PROPERTY getters and setters. Read articles about Qt object model and meta object system more carefully.
Quotation from QMetaObject class description (http://doc.trolltech.com/4.6/qmetaobject.html#details):
"method() and methodCount() provide information about a class's meta-methods (signals, slots and other invokable member functions)."
There is no information about normal C++ methods access. And actually it's good since reflective techniques are slow.