I cannot access staticmetaobject and I dont know why. I would need some help.
Here is the code
The two errors are:
staticMetaObject is not a member of MainWIndow*
I feel like it has something to do with the list, but I'm not sure.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "form.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Form<MainWindow*>* form;
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
/*qDebug() << MainWindow::staticMetaObject.className();
if (QString(MainWindow::staticMetaObject.className()) == QString("MainWindow")) {
qDebug() << "test";
}*/
form = new Form<MainWindow*>(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
form->myFunc();
}
form.h
#ifndef FORM_H
#define FORM_H
#include <QObject>
#include <QDebug>
class FormBase : public QObject
{
Q_OBJECT
public:
FormBase() {}
};
template <typename T>
class Form : public FormBase, public QList<T>
{
public:
Form(T a)
{
QList<T>::append(a);
}
void myFunc()
{
qDebug() << T::staticMetaObject.className();
}
};
#endif // FORM_H
You are getting you types confused.
You want T to be MainWindow so that you can do
T::staticMetaObject.className()
That means you want a QList<T*>. You derive from that so you can just call
append(a);
The following code compiles fine:
class FormBase : public QObject
{
Q_OBJECT
public:
FormBase() {}
};
template <typename T>
class Form : public FormBase, public QList<T*>
{
public:
Form( T* a )
{
append( a );
}
void myFunc()
{
qDebug() << T::staticMetaObject.className();
}
};
class MainWindow:
public QMainWindow
{
MainWindow()
{
form = new Form<MainWindow>( this );
}
FormBase* form;
};
Related
I have a QMainWindow Application which also includes an QStackedWidget.
The pages of the QstackedWidget are promoted to ui widgets for example heating_widget.ui
If I use a button slot on my QMainWindow I can use this to get my application to fullscreen:
void SmartHome::on_fullscreen_on_clicked()
{
SmartHome::setWindowState(Qt::WindowFullScreen);
}
But how can I do this from a button which is in the heating_widget.cpp file?
Using:
void heating_widget::on_fullscreen_on_clicked()
{
SmartHome::setWindowState(Qt::WindowFullScreen);
}
obviously doesn't work and throws this error at me:
cannot call member function 'void
QWidget::setWindowState(Qt::WindowStates)' without object
SmartHome::setWindowState(Qt::WindowFullScreen);
I know this has something to do with parent() but I can't get it to work.
Do you have any idea?
My smarthome.h file:
#ifndef SMARTHOME_H
#define SMARTHOME_H
#include <QTime>
#include <QMainWindow>
namespace Ui {
class SmartHome;
}
class SmartHome : public QMainWindow
{
Q_OBJECT
public:
explicit SmartHome(QWidget *parent = 0);
~SmartHome();
private slots:
void on_Info_Button_clicked();
void on_News_Button_clicked();
void on_Heating_clicked();
void timerslot();
void on_Config_clicked();
void on_About_clicked();
public slots:
void setFullscreen();
private:
Ui::SmartHome *ui;
QTimer* myTimer;
};
#endif // SMARTHOME_H
My heating_widget.h :
#ifndef HEATING_WIDGET_H
#define HEATING_WIDGET_H
#include "smarthome.h"
#include <QWidget>
namespace Ui {
class heating_widget;
class SmartHome;
}
class heating_widget : public QWidget
{
Q_OBJECT
public:
explicit heating_widget(QWidget *parent = 0);
~heating_widget();
private slots:
void on_fullscreen_on_clicked();
private:
Ui::heating_widget *ui;
};
#endif // HEATING_WIDGET_H
and my heating.widget.cpp:
#include "heating_widget.h"
#include "ui_heating_widget.h"
#include "smarthome.h"
#include "iostream"
heating_widget::heating_widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::heating_widget)
{
ui->setupUi(this);
QObject::connect(ui->fullscreen_on, SIGNAL(clicked()), this , SLOT(SmartHome::setFullscreen()));
}
heating_widget::~heating_widget()
{
delete ui;
}
void heating_widget::on_fullscreen_on_clicked()
{
parentWidget()->setWindowState(Qt::WindowFullScreen);
std::cout<<"clicked"<<std::endl;
}
I would do it in the following way:
void heating_widget::on_fullscreen_on_clicked()
{
foreach(QWidget *widget, QApplication::topLevelWidgets()) {
if (auto mainWindow = qobject_cast<SmartHome *>(widget)) {
mainWindow->setWindowState(Qt::WindowFullScreen);
}
}
}
The idea is finding your main window among application top level widgets and change its state. This code can be called from anywhere in your application regardless of the windows hierarchy.
My app, consists in 2 different object (QObject and QMainWIndow), and I am wondering how to communicate between them with SLOT/SIGNAL. Moreover, does existing better approach ?
Can someone make an simple example ? Thank :)
sample
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "ui_mainwindow.h"
#include "object.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
private slots:
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "object.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->chkState, SIGNAL(clicked()), this, SLOT(object->chkState();));
}
MainWindow::~MainWindow()
{
delete ui;
}
object.h
#ifndef OBJET_H
#define OBJET_H
#include "mainwindow.h"
#include <QMainWindow>
#include <QObject>
class Object : public QObject
{
Q_OBJECT
public:
explicit Object(QObject *parent = 0);
bool state;
signals:
private slots:
void chkState(Ui::MainWindow *ui);
};
#endif // OBJET_H
objet.cpp
#include "object.h"
#include "mainwindow.h"
Object::Object(QObject *parent) : QObject(parent)
{
}
void Object::chkState(Ui::MainWindow *ui)
{
if (ui->chkState->isChecked())
{
ui->state->setText("true");
state = true;
}
else
{
ui->state->setText("false");
state = false;
}
}
Here is a simple example of how to emit signals and slots.
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "object.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void transmit_to_object(bool value);
private slots:
void receive_from_object(bool value);
void on_checkBox_clicked();
private:
Ui::MainWindow *ui;
object m_object;
};
#endif // MAINWINDOW_H
#ifndef OBJECT_H
#define OBJECT_H
#include <QObject>
class object : public QObject
{
Q_OBJECT
public:
explicit object(QObject * parent = 0);
signals:
void transmit_to_gui(bool value);
private slots:
void receive_from_gui(bool value);
private:
bool state;
};
#endif // OBJECT_H
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(&m_object,SIGNAL(transmit_to_gui(bool)),this,SLOT(receive_from_object(bool)));
connect(this,SIGNAL(transmit_to_object(bool)),&m_object,SLOT(receive_from_gui(bool)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::receive_from_object(bool value)
{
if(value)
{
ui->lineEdit->setText("true");
}
else
{
ui->lineEdit->setText("false");
}
}
void MainWindow::on_checkBox_clicked()
{
if(ui->checkBox->isChecked())
{
emit transmit_to_object(true);
}
else
{
emit transmit_to_object(false);
}
}
#include "object.h"
#include "mainwindow.h"
object::object(QObject *parent)
{
}
void object::receive_from_gui(bool value)
{
state = value;
emit transmit_to_gui(state);
}
There are several errors in your code.
First:
connect(ui->chkState, SIGNAL(clicked()), this, SLOT(object->chkState();));
Here you say:
"when we click on the ui->chkState, I want you call a function in this, which is the object->chkState slot". That's definitly not what you want.
What is object ? this object hasn't been created. What you want is :
connect(ui->chkState, SIGNAL(clicked()), myobject, SLOT(chkState()));
with myobject an object of type Object so you need to add in your mainwindow.h a
Object *myobject;
and in your mainwindow.cpp before the connect:
myobject = new Object(this);
Moreover, your function void chkState(Ui::MainWindow *ui); won't work because you cannot get the mainwindow ui in parameter like that.
What I advise you to do, if it's only for tests so you know that parent is the type of MainWindow, you can do:
void Object::chkState()
{
MainWindow* parent = static_cast<MainWindow*>(parent());
if (parent->ui->chkState->isChecked())
{
parent->ui->state->setText("true");
state = true;
}
else
{
parent->ui->state->setText("false");
state = false;
}
}
So the parameter in your slot is removed.
I know this question asked many times but still confused and cannot find a solution.
I have a MainWindow and a class.
In my class I have a signal which I emit in the method call.
Problem: Slot method is not firing.
Here is my code.
BWorker.h
#pragma once
#include <QObject>
class BWorker : public QObject
{
Q_OBJECT
public:
BWorker(QObject *parent);
~BWorker();
void doSomething();
signals:
void signalSomething();
};
BWorker.cpp
#include "BWorker.h"
BWorker::BWorker(QObject *parent)
: QObject(parent)
{
}
BWorker::~BWorker()
{
}
void BWorker::doSomething()
{
emit signalSomething();
}
QtGuiApplication1.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_QtGuiApplication1.h"
class QtGuiApplication1 : public QMainWindow
{
Q_OBJECT
public:
QtGuiApplication1(QWidget *parent = Q_NULLPTR);
public slots:
void workDone();
private:
Ui::QtGuiApplication1Class ui;
};
QtGuiApplication1.cpp
#include "QtGuiApplication1.h"
#include "BWorker.h"
QtGuiApplication1::QtGuiApplication1(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
BWorker bworker(this);
connect(&bworker, SIGNAL(bworker.signalSomething), this, SLOT(workDone()));
bworker.doSomething();
}
void QtGuiApplication1::workDone() {
}
Your problem is here:
SIGNAL(bworker.signalSomething)
This is not valid and you should see a message in terminal saying that there is no such signal. The correct syntax for your case would be:
SIGNAL(signalSomething())
Please post your code by copy-pasting it. Do not edit the code: The problem could be emerged from where you edited.
The code of mine worked fine.
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void workDone();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include "worker.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
Worker worker(this);
connect(&worker, SIGNAL(signalSomething()), this, SLOT(workDone()));
//connect(&worker, &Worker::signalSomething, this, &MainWindow::workDone);
worker.doSomething();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::workDone()
{
qDebug() << "Done.";
}
worker.h:
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0);
void doSomething();
signals:
void signalSomething();
public slots:
};
#endif // WORKER_H
worker.cpp:
#include "worker.h"
Worker::Worker(QObject *parent) : QObject(parent)
{
}
void Worker::doSomething()
{
emit signalSomething();
}
Application Output:
Debugging starts
Done.
Debugging has finished
Printed out "Done." means the codes are working.
I have made made a DDisplay class to display my data on gui text box but I have some strange situation, when I call the function from mainwindow class it is working fine but when I try to call the same function from other class it is not working. below is the small code my program
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <ddisplay.h>
#include <QMainWindow>
#include "test.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
DDisplay b;
Test c;
private slots:
void display(const QString &a);
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QObject::connect(&b,SIGNAL(display(QString)),this,SLOT(display(QString)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::display(const QString &a){
ui->textBrowser->setText(a);
}
void MainWindow::on_pushButton_clicked()
{
b.printf("hello"); //this function working fine
//c.printf("lllll"); //not working
}
test.h
#ifndef TEST_H
#define TEST_H
#include <QString>
#include <ddisplay.h>
class Test
{
public:
Test();
void printf(const QString &a);
DDisplay b;
};
test.cpp
#include "test.h"
Test::Test()
{
}
void Test::printf(const QString &a){
b.printf(a);
}
ddisplay.h
#include
class DDisplay : public QObject
{
Q_OBJECT
public:
explicit DDisplay(QObject *parent = 0);
void printf(const QString &a);
QString b;
signals:
void display(const QString &a);
public slots:
};
ddisplay.cpp
#include "ddisplay.h"
DDisplay::DDisplay(QObject *parent) :
QObject(parent)
{
}
void DDisplay::printf(const QString &a)
{
b+=a;
emit display(b);
}
c.printf("lllll"); //not working
It's not working because you don't have a connect for this object. DDisplay in Test class is a dfferent instance than that in a MainWindow.
One possible solution for your question in comments below is to connect DDisplay's signal and MainWindow's slot either in main.cpp or in specialized initialization class.
I want to convert a QString from another class toInt, but it seams to fail because the result is 0 while it should be 5 and the rest of the code works.
Because I am new to C/Qt and find classes a bit confusing, I think I have done something wrong with my classes.
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
MyClass tmp;
int myNumber = tmp.m_replyStr.toInt();
ui->lcdNumber->display(myNumber);
}
MyClass::MyClass()
{
m_manager = new QNetworkAccessManager(this);
connect( m_manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
}
void MyClass::fetch()
{
m_manager->get(QNetworkRequest(QUrl("http://example.tld/test.html"))); // html contains only the number 5
}
void MyClass::replyFinished(QNetworkReply* pReply)
{
QByteArray data=pReply->readAll();
QString str(data);
m_replyStr = str;
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QObject>
#include <QNetworkAccessManager>
#include <QUrl>
#include <QNetworkRequest>
#include <QNetworkReply>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void on_pushButton_clicked();
private:
Ui::Widget *ui;
};
class MyClass : public QObject
{
Q_OBJECT
public:
MyClass();
void fetch();
QString m_replyStr;
public slots:
void replyFinished(QNetworkReply*);
private:
QNetworkAccessManager* m_manager;
};
#endif // WIDGET_H
You're accessing m_replyStr of a newly initialised instance tmp, which doesn't set anything into its m_replyStr. So it has the default-initialised value of "empty string."
EDIT
Based on your follow-up question, perhaps you were looking for something like this?
class MyClass;
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(MyClass &myClassInstance, QWidget *parent = 0);
~Widget();
private slots:
void on_pushButton_clicked();
private:
Ui::Widget *ui;
MyClass *myClass;
};
Widget::Widget(MyClass &myClassInstance, QWidget *parent = 0)
: QWidget(parent)
, ui(new Ui::Widget)
, myClass(&myClassInstance)
{
ui->setupUi(this);
}
void Widget::on_pushButton_clicked()
{
int myNumber = myClass->m_replyStr.toInt();
ui->lcdNumber->display(myNumber);
}