How to access QMainWindow from another class - c++

// mainwindow.h
#include "ui_MainWindow.h"
#include "parseTextFile.h"
class MainWindow:public QMainWindow
{
Q_OBJECT
public:
MainWindow(void);
private:
Ui_mainWindow ui;
parseFile *fileParse;
public slots:
int onOkButtonClick();
};
// mainwindow.cpp
MainWindow::MainWindow(void)
{
ui.setupUi(this);
connect(ui.OkButton,SIGNAL(clicked()),this,SLOT(onOkButtonClick()));
}
int MainWindow::onOkButtonClick()
{
fileParse = new parseFile(this);
fileParse->parseTextFile();
return 0;
}
int main(int argc,char* argv[])
{
QApplication app(argc,argv);
MainWindow *mainWindow = new MainWindow();
mainWindow->show();
return app.exec();
}
// parseTextFile.h
class parseFile
{
public:
parseFile(QWidget *parent =0);
~parseFile();
int parseTextFile( );
};
// parseTextFile.cpp
#include "parseTextFile.h"
#include <QMessageBox>
parseFile::parseFile(QWidget *parent)
{
}
parseFile::~parseFile()
{
}
int parseFile::parseTextFile( )
{
QMessageBox::information(this,"a","b");
return 0;
}
I can able to access parseTextFile method but i am getting error in QMessageBox. Is it the right way?
How to print QMessageBox in parseTextFile class?
anything needs to add in parseTextFile constructor?

Pass this to QMessageBox::information as a parent is not a valid argument because parseFile is not a QWidget derived class.
For simple, just pass nullptr instead of this :
QMessageBox::information(nullptr ,"a","b");
In this case, the message box belongs to no one. It's will be closed by the user or when the application exits.
PS: you should release the memory after using fileParse to avoid memory leaks.
There are several ways to like with the main window (static pointer, singleton, top widgets enumeration,etc.) but the simplest one, that I thinks you intend to do, is to make parseFile class as QObject derived class and QMainWindow its parent.
class parseFile: public QObject
{
Q_OBJECT
public:
parseFile(QWidget *parent =0);
~parseFile();
int parseTextFile();
};
parseFile::parseFile(QWidget *parent)
:QObject(parent)
{
}
int parseFile::parseTextFile()
{
QWidget * parentWidget = qobject_cast<QWidget *>( parent() ); //<-- QMainWindow instance
QMessageBox::information( parentWidget, "a", "b");
return 0;
}
int MainWindow::onOkButtonClick()
{
fileParse = new parseFile(this);
fileParse->parseTextFile( );
//fileParse should be released by:
//fileParse->deleteLater();
return 0;
}

Related

QObject connection "Cannot convert argument 3 from 'Class that in Inherits QObject' to QObject*

I'm using the MVC pattern and I'm trying to connect a signal from my view class with my controller class that inherits QObject
class View : public QWidget
{
Q_OBJECT
private:
Controller* controller;
QPushButton* startButton;
void addControls(QVBoxLayout* mainLayout);
public:
explicit View(QWidget *parent = nullptr);
void setController(Controller* c);
};
#endif // VIEW_H
This are the methods
void View::addControls(QVBoxLayout *mainLayout)
{
//I'm adding the button
}
View::View(QWidget *parent) : QWidget(parent)
{
//Layout
}
void View::setController(Controller *c){
controller = c;
connect(startButton, SIGNAL(clicked()), controller, SLOT(begin()));
//ERROR controller is a Controller* and it can't be converted it to const QObject*
}
And this is the Controller class
class Controller : public QObject
{
Q_OBJECT
private:
QTimer* timer;
View* view;
Model* model;
public:
explicit Controller(QObject *parent = nullptr);
~Controller();
void setModel(Model* m);
void setView(View* v);
public slots:
void begin() const;
};
#endif // CONTROLLER_H
And the methods
Controller::Controller(QObject *parent):
QObject(parent), timer(new QTimer)
{
connect(timer, SIGNAL(timeout()), this, SLOT(next()));
}
Controller::~Controller() { delete timer; }
void Controller::setModel(Model* m) { model = m; }
void Controller::setView(View* v) { view = v; }
void Controller::begin() const {
timer->start(200);
}
For good measure, here is the main where I set each component
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
View w;
Controller c;
Model m;
c.setModel(&m);
c.setView(&w);
w.setController(&c);
w.show();
return a.exec();
}
I've tried everything I could think of, can't make it work..
Stop using the terrible text-based slot connection interface.
Use the modern one that gives nice compile errors:
QObject::connect(startButton, &QPushButton::clicked, controller, &Controller::begin);

Linking a QWidget to another QWidget new created

I am try to, by pressing a button in the main QWidget, to create a new QWidget. In that new created QWidget I want to have a button connected to a slot of the main QWidget.
class UI : public QWidget
{
public:
UI(){connection();};
private:
QPushButton* all = new QPushButton{ "ALL" };
void connection(){
QObject::connect(all,QPushButton::clicked,[](){
SmallGUI* s=new SmallGUI{};
s->show();
});
}
void something(){
//something
}
and the second class
class SmallGUI1 :
public QWidget
{
public:
SmallGUI(){connection();};
private:
QPushButton* N =new QPushButton;
void connection(){
//to connect N to something()
}
I want to connect N to something() .
Before we start, there are some other problems with you code.
Note that in your second class, the constructor is not named the same as the class, which will cause some... Problems.
You also forgot to put a parent for your buttons (which may thus cause some unexpected results) AND for your Widgets (which is again not a good idea).
So, that being said, let us get to the main topic.
I tend to only put prototypes and declare the attributes in the .h file to make the code clearer, but you may of course adapt it to your needs or to your own programming convention.
There are several ways to do something like this, but the simplest one should look like this :
SmallGUI1.h :
#include "UI.h" //The file in which the class UI is declared
//OR :
//class UI; //If you need to include this file in UI.h
class SmallGUI1 : public QWidget{
Q_OBJECT //Q_OBJECT macro, check the doc for more explainations about it
public:
explicit SmallGUI1(UI *parent = nullptr); //Explicit means that this constructor cannot be used for implicit casts
~SmallGUI1();//Destructor needed because I only put the constructor above
private:
QPushButton* N; //Not very good looking to initialize attributes in the .h in my opinion, but works fine.
}
SmallGUI1.cpp :
SmallGUI1::SmallGUI1(UI *parent) : QWidget(parent){
N = new QPushButton(tr("Some text on the button") , this); //tr to enable translation on this string
//************* If I understood your question correctly, this is what you are looking for *************
connect(N , &QPushButton::clicked , parent , &UI::doSomething); //Select the signal you want
/*
Some code here
*/
show();
}
SmallGUI1::~SmallGUI1(){qDeleteAll(children());}
UI.h :
class UI : public QWidget{
Q_OBJECT
public:
explicit UI(QWidget *parent = nullptr);
~UI();
private:
QPushButton* all;
private slots :
void createSmallGUI1();
void doSomething();
}
UI.cpp :
#include "SmallGUI1.h"
UI::UI(QWidget *parent) : QWidget(parent){
all = new QPushButton(tr("ALL") , this);
connect(all , &QPushButton::clicked , this , &UI::createSmallGUI1);
/*
Some code here
*/
}
UI::~UI(){qDeleteAll(children());}
void UI::createSmallGUI1(){SmallGUI1 *gui = new SmallGUI1(this);}
void UI::doSomething(){
/*
Clever code here
*/
}
You can define the second widget as a child of the main widget to make things easier:
class UI : public QWidget {
...
private:
SmallGUI* s;
...
and then initialize it in the UI constructor, along with your all button. You can initially hide the child widget or disable it:
UI() {
all = new QPushButton{"ALL", this};
setWindowTitle("UI"); // just for clarification
s = new SmallGUI(this);
s->hide();
connection();
};
and 'show' it with button clicked signal
connect(all, &QPushButton::clicked, s, &SmallGUI::show);
Doing so gives you the option to connect the clicked signal of your N button to the something function in the parent class
connect(s->N, &QPushButton::clicked, this, &UI::something);
The complete program would be as follows,
#include <QApplication>
#include <QMessageBox>
#include <QPushButton>
#include <QWidget>
class SmallGUI : public QWidget {
public:
SmallGUI(QWidget* parent) : QWidget(parent) {
N = new QPushButton{"btn2", this};
connection();
};
QPushButton* N;
private:
void connection(){};
};
class UI : public QWidget {
public:
UI() {
all = new QPushButton{"ALL", this};
setWindowTitle("UI"); // just for clarification
s = new SmallGUI(this);
s->hide();
connection();
};
private:
SmallGUI* s;
QPushButton* all;
void connection() {
connect(all, &QPushButton::clicked, s, &SmallGUI::show);
connect(s->N, &QPushButton::clicked, this, &UI::something);
}
void something() { QMessageBox::information(this, "Hello", "Hello"); }
};
int main(int argc, char* argv[]) {
QApplication a(argc, argv);
UI w;
w.show();
return a.exec();
}
It is not good idea to connect to parent's slots from "nested" class, since SmallGUI1 will be tied to class UI.
Here is better solution, I think:
class UI : public QWidget
{
public:
UI(){connection();};
private:
QPushButton* all = new QPushButton{ "ALL" };
void connection(){
QObject::connect(all,QPushButton::clicked,[](){
SmallGUI1* s=new SmallGUI1;
connect(s,&USmallGUI1::button_clicked,this,&UI::something);
s->show();
});
}
void something(){
//something
}
And SmallGUI1 class:
class SmallGUI1 :
public QWidget
{
public:
SmallGUI1(){connection();};
signals:
void button_clicked();
private:
QPushButton* N;
void connection(){
//to connect N to something()
N = new QPushButton;
connect(N,&QPushButton::clicked,this,&SmallGUI1::button_clicked)
}
This way, you are connecting QPusButton::clicked signal from SmallGUI1 to the signal SmallGUI1::button_clicked(). Dont need to implement additional slot, just connect signal to signal.
And in UI you are connecting button_clicked() signal to the slot dosomething()
DONT FORGET THE CONSTRUCTOR OF SmallGUI1! In your code, SmallGUI() will be just a method, which will not be called when SmallGUI1 is instantiated, and you have to call it by yourself.

How to implement signal and slots in QGraphicsRectItem? subclassed qobject and qgraphicsrectitem but getting errors

I am creating object from QGraphicsRectItem and adding to the Qgraphicscene(scene).
I want to get every movement(pos) of object(qgraphicsrectitem) so that I subclassed Qgraphicsrectitem. But in this class I am getting some errors.
How can I get object position changed in scene ?
error:
'staticMetaObject' is not a member of 'QGraphicsRectItem'
{ &QGraphicsRectItem::staticMetaObject, qt_meta_stringdata_ItemHandler.data
ItemHandler.h
#include <QObject>
#include <QGraphicsRectItem>
class ItemHandler : public QGraphicsRectItem, public QObject
{
Q_OBJECT
public:
ItemHandler(QGraphicsItem *parent = 0 );
~ItemHandler();
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
signals:
void objectHandlePosChanged(QPointF value);
};
ItemHandler.cpp
#include "itemhandler.h"
ItemHandler::ItemHandler(QGraphicsItem *parent) : QGraphicsRectItem(parent)
{
setFlag(QGraphicsItem::ItemSendsGeometryChanges);
}
ItemHandler::~ItemHandler()
{
}
QVariant ItemHandler::itemChange(QGraphicsItem::GraphicsItemChange change,
const QVariant &value)
{
QPointF newPos = value.toPointF();
emit objectHandlePosChanged(newPos);
}
In you header file, inherit first from QObject, as follows:
#include <QObject>
#include <QGraphicsRectItem>
class ItemHandler : public QObject, public QGraphicsRectItem
{
Q_OBJECT
public:
ItemHandler(QGraphicsItem *parent = 0 );
~ItemHandler();
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
signals:
void objectHandlePosChanged(QPointF value);
};
And this is my test main function (sorry it's just a sandbox):
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow* mywindow = new MainWindow();
QGraphicsScene scene;
ItemHandler *item = new ItemHandler;
item->setRect(10.0, 10.0, 10.0, 10.0);
scene.addItem(item);
QApplication::connect(item, SIGNAL(objectHandlePosChanged(QPointF)), mywindow, SLOT(moved(QPointF)));
QGraphicsView view(&scene);
view.setFixedSize(250, 250);
view.setWindowTitle("QGraphicsItem Test");
item->setPos(-100, -100);
item->setPos(-200, -200);
view.show();
return app.exec();
}
I just used an empty MainWindow that is never displayed to have a slot to connect to the signal, there's no point in having a MainWindow: it was already there and I modified it instead of creating a new class. The example works, fires the signal and displays the rectangle.

Sending QPixmap pointer via signal-slots, empty pixmap data

I have problem with sharing pointer to Pixmap via signal-slot mechanism.
Inside slot function I have correct QPixmap with fulled data.
In reciever I have unaccessible QPixmap with empty data.
Any ideas?
class A
{
public:
A:A():pixmap(0){};
void fillPixmap()
{
// correct Pixmap and data isn't null
}
public signals:
void sendQPixmapToB(QPixmap*);
private:
QPixmap *pixmap;
}
class B
{
public:
B:B(){};
public slots:
void recievePixmap(QPixmap* pixmap)
{
// here in debugger pixmap is unaccesible and data is 0
}
}
void onButtonClicked()
{
a.fillPixmap();
}
int main()
{
A a;
B b;
.....
connect(a, SIGNAL(sendQPixmapToB(QPixmap*)),b,SLOT(recievePixmap(QPixmap*)));
return 0;
}
I can not tell you what is wrong with your code because as you indicate you are showing a pseudo-code, so I will show you the correct way to do it.
#include <QGuiApplication>
#include <QPixmap>
#include <QTimer>
#include <QDebug>
class A: public QObject{
Q_OBJECT
public:
using QObject::QObject;
void sendPixmap(){
fillPixmap();
emit sendQPixmapToB(pixmap);
}
signals:
void sendQPixmapToB(const QPixmap & pixmap);
private:
void fillPixmap(){
pixmap = QPixmap(64, 64);
pixmap.fill(Qt::red);
}
QPixmap pixmap;
};
class B: public QObject{
Q_OBJECT
public:
using QObject::QObject;
public slots:
void recievePixmap(const QPixmap & pixmap){
qDebug()<<pixmap;
}
};
int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv);
A obja;
B objb;
QObject::connect(&obja, &A::sendQPixmapToB, &objb, &B::recievePixmap);
QTimer::singleShot(1000, &obja, &A::sendPixmap);
return a.exec();
}
#include "main.moc"ยท

Implementing c++ Callback using Qt Signal and Slot

I have created a library which has following interface and callback.
I wanted to Implent it using QT Signal and Slot.
Is is possible to replace IWifiCameraDiscovery with Signal and slot
class IWifiCameraDiscovery
{
public:
virtual int InitialiseWiFiDiscovery(IWifiCameraEnumerationCallback*) = 0;
virtual void UnInitialiseWiFiDiscovery() = 0;
virtual int EnumerateWiFiDevice() = 0;
};
class IWifiCameraEnumerationCallback
{
public:
virtual void onWiFiDeviceDiscovered( WiFiDeviceInfo* pDeviceInfo,unsigned short nNoOfDevice) = 0;
virtual void onDiscoveryTimeout() = 0;
};
Yes, in a quite straightforward way.
class IWifiCameraDiscovery
{
public:
virtual int InitialiseWiFiDiscovery() = 0;
virtual void UnInitialiseWiFiDiscovery() = 0;
virtual int EnumerateWiFiDevice() = 0;
signals:
void onWiFiDeviceDiscovered(WiFiDeviceInfo* pDeviceInfo, unsigned short nNoOfDevice);
void onDiscoveryTimeout();
};
In your implementation, instead of calling the callbacks directly:
callback.onWiFiDeviceDiscovered(pDevInfo, x);
You would emit a signal:
emit onWiFiDeviceDiscovered(pDevInfo, x);
And you would use QObject::connect to connect these signals to your actual receivers (slots) on the other end. Be aware that emitting a signal is more expensive than calling a virtual function.
try this simple example
#include <QApplication>
#include <QFont>
#include <QPushButton>
#include <QWidget>
class MyWidget : public QWidget
{
public:
MyWidget(QWidget *parent = 0);
};
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)
{
setFixedSize(200, 120);
QPushButton *quit = new QPushButton(tr("Quit"), this);
quit->setGeometry(62, 40, 75, 30);
quit->setFont(QFont("Times", 18, QFont::Bold));
connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyWidget widget;
widget.show();
return app.exec();
}
you can use like this
class IWifiCameraDiscovery
{
public slots:
void UnInitialiseWiFiDiscovery();
signals:
void EnumerateWiFiDevice();
}