Why cannot write a QWidget class in the main.cpp? - c++

Update:
If I delete Q_OBJECT, and I do not use SLOT SINGAL, just use connect() like this:
connect(this, &QWidget::destroyed, this, &QWidget::myslot),
my code will run well without any warnings and errors.
I want to write a little code to instruct some classes, so I try to simplify my code. But I encountered some strange things. I cannot write a simple widget in my main.cpp. If I write the widget in mywidget.cpp and mywidget.h, the program runs well. If I want to write the widget in the main.cpp, what should I do?
This is my code.
#include <QApplication>
#include <QWidget>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
};
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
}
Widget::~Widget()
{
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
And the error information is:

Add following line to the end of main.cpp and rerun qmake:
#include "main.moc"
That will invoke moc tool for your main.cpp. It generates meta-object function definitions for your Widget class resolving your linker errors when you rebuild.

As stated in documentation:
Whenever qmake is run, it parses the project's header files and
generates make rules to invoke moc for those files that contain a
Q_OBJECT macro.
Thus, put the class declaration in a header file (e.g. widget.h) and the class definition in a source file with the same name (e.g. widget.cpp).

If you still want to make it work with signals you can remove the Q_OBJECT macro and use the QObject::connect()
for example:
#include <QApplication>
#include <QWidget>
#include <iostream>
class Widget : public QWidget
{
//Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
};
Widget::Widget(QWidget *parent) : QWidget(parent)
{
// say bey
QObject::connect(this,&Widget::destroyed,
[](){std::cout<<"bye"<<std::endl;});
}
Widget::~Widget()
{
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
I test it on Qt5.9.4

Related

Class inherited from QLabel, why custom slot is not called?

I made class inherited from QLabel. This class also have public slot, that should change label caption. I "call" this SLOT with clicked() SIGNAL of button.
So nothing happened when I press the button.
#include <QApplication>
#include <QLabel>
#include <QPushButton>
class Label : public QLabel
{
public:
Label(QString a) : QLabel(a){}
public slots:
void change()
{
this->setNum(2);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPushButton* button = new QPushButton("Button");
Label* lbl = new Label("Label");
button->show();
lbl->show();
QObject::connect(button, SIGNAL(clicked(bool)), lbl, SLOT(change()));
return a.exec();
}
What should I do to change caption from slot?
In order for the signals and slots to be recognized, the classes must use the Q_OBJECT macro in the private part.
Another thing to do is to include "main.moc", for more information on this point read this.
#include <QApplication>
#include <QLabel>
#include <QPushButton>
class Label : public QLabel
{
Q_OBJECT
public:
Label(const QString &text, QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
QLabel(text, parent, f){}
public slots:
void change()
{
setNum(2);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPushButton* button = new QPushButton("Button");
Label* lbl = new Label("Label");
button->show();
lbl->show();
QObject::connect(button, SIGNAL(clicked()), lbl, SLOT(change()));
return a.exec();
}
#include "main.moc"
At the end of making these changes you must execute the following:
Press clean all in the Build menu.
then run qmake in the same menu.
And you just compose your project.
Add Q_OBJECT after
class Label : public QLabel
{
and then you should
either place your Label class declaration to a .h file or write #include "main.moc" after main function declaration.
try to get the return value from your connect call an check it for true or false.
Add Q_OBJECT Macro to the beginning of your derived class.
Add some debug output to your slot like
qDebug()<<"This is my slot.";
Maybe this would help to get a little further.
Best regards

Why does this code create two objects while one is needed?

This is a tutorial code for Qt:
Header file:
#include <QMainWindow>
namespace Ui {
class Notepad;
}
class Notepad : public QMainWindow
{
Q_OBJECT
public:
explicit Notepad(QWidget *parent = 0);
~Notepad();
private:
Ui::Notepad *ui;
};
Source file:
#include "notepad.h"
#include "ui_notepad.h"
Notepad::Notepad(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Notepad)
{
ui->setupUi(this);
}
Notepad::~Notepad()
{
delete ui;
}
And in main,
#include "notepad.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Notepad w;
w.show();
return a.exec();
}
So when we do Notepad w, an object is already created on the stack, and why does the code still create another object on the heap using new and assign to a member?
The one on the stack is of type Notepad, and it's the application's main window. The dynamic one is of type Ui::Notepad. That's a class automatically generated by Qt's uic tool; it contains the widgets created in UI creator as data members.
In a way, you could say that Notepad is concerned with the logic and uses an instance of Ui::Notepad to provide the GUI for it.

Qt Designer - How to connect a signal to a static function?

Okay I'm using Qt Designer to build a GUI. I've managed to figure out how to make the menuBar and I've added some actions to the bar, but now I need to connect the actions to make them do something.
Specifically, on my file menu, I have the simple open action. I want this action to run a function that calls my QFileDialog and so on, but I don't know how to do this.
So, how do I connect my actionOpen to my static function?
I am using the latest Qt, 5.0.2
I'm a little frustrated here. This is obviously one of the most basic things someone might need to do, yet I cannot find any real solution to this anywhere on the web. From the lacking Qt wiki, to other people's questions, nobody really seems to have a clear answer. There are answers for older versions of Qt, yet in those old versions apparently signals couldn't connect to static functions, so those are irrelevant. And nobody seems to know how to do this through the Qt Designer. Also, nobody ever clarifies where to put what.
I have this line in my main.cpp file:
QObject::connect(actionOpen, &actionOpen::triggered, fileOpen)
I have an object called 'actionOpen' made in Qt Designer, there is a signal called triggered, and I have a function defined just below my main inside main.cpp called 'fileOpen'. This seems to follow the proper syntax, yet it throws many errors.
Also, I can repeatedly click build in Qt Creator and every single time it comes up with a different number of errors, disappearing and reappearing, without me even touching the code. I'm starting to think this IDE is sort of a POS.
EDIT:
Here are my files. Maybe this will help somewhat.
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 fileOpen();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <iostream>
using namespace std;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
QObject::connect(ui->actionOpen, &QAction::triggered, &MainWindow::fileOpen);
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void fileOpen()
{
/*
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), QString(),
tr("Text Files (*.txt);;C++ Files (*.cpp *.h)"));
if (!fileName.isEmpty()) {
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox::critical(this, tr("Error"), tr("Could not open file"));
return;
}
QTextStream in(&file);
ui->textEdit->setText(in.readAll());
file.close();
}
*/
cout << "Hello!";
}
The second argument is incorrect. You should specify the class name, not object name. So it should be:
QObject::connect(actionOpen, &QAction::triggered, fileOpen);
Complete working example (tested):
void fileOpen() {
qDebug() << "ok";
}
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QMenu menu;
QAction* actionOpen = menu.addAction("test");
QObject::connect(actionOpen, &QAction::triggered, fileOpen);
menu.show();
return a.exec();
}
1.) Create regular slot and call the static function.
OR
2.) I suppose you could create a singleton Q_OBJECT class and connect to it - of course like option 1 you'd then make the call to whatever static/global function.
/**
* Pseudo-code!, the singleton should be in its own header file
* not in the global main.cpp file.
*/
class Singleton : public QObject
{
Q_OBJECT
public:
Singleton() : QObject() {}
static Singleton* getInstance() {
if(!_instance) _instance = new Singleton();
return _instance;
}
public slots:
void mySlot() { qDebug() << __FILE__ << " " << __FUNCTION__ << __LINE__;
}
private:
static Singleton* _instance;
};
Singleton* Singleton::_instance = NULL;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
Singleton* instance = Singleton::getInstance();
QObject::connect(&w, SIGNAL(destroyed()), instance, SLOT(mySlot()));
return a.exec();
}
I'm just trying my best to answer the question, but like many of the comments above - this isn't something that I've needed ever needed to do. I can say that QtCreator/Designer is a really amazing tool and as you overcome some of the learning curves it'll be less frustrating.

How can I put this qt program into one source code file

I want to have this code in one file, but can't figure out how to. I know it might not be good practice to do so but I am trying to learn qt, and would find it easier to understand the information if it were in one file.
This is the main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.showMaximized();
return app.exec();
}
This is the mainwindow.cpp
#include "mainwindow.h"
#include <QCoreApplication>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Create the button, make "this" the parent
m_button = new QPushButton("My Button", this);
// set size and location of the button
m_button->setGeometry(QRect(QPoint(100, 100),
QSize(200, 50)));
// Connect button signal to appropriate slot
connect(m_button, SIGNAL(released()), this, SLOT(handleButton()));
}
void MainWindow::handleButton()
{
// change the text
m_button->setText("Example");
// resize button
m_button->resize(100,100);
}
this is the mainwindow.h
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private slots:
void handleButton();
private:
QPushButton *m_button;
};
By just copying everything in one file.
#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private slots:
void handleButton();
private:
QPushButton *m_button;
};
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Create the button, make "this" the parent
m_button = new QPushButton("My Button", this);
// set size and location of the button
m_button->setGeometry(QRect(QPoint(100, 100),
QSize(200, 50)));
// Connect button signal to appropriate slot
connect(m_button, SIGNAL(released()), this, SLOT(handleButton()));
}
void MainWindow::handleButton()
{
// change the text
m_button->setText("Example");
// resize button
m_button->resize(100,100);
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.showMaximized();
return app.exec();
}
It is usually not a good idea to define new classes in same file as your main. Generally you want new classes each in their own file or you would want to put several related classes together in a seperate file. There are a tonne of resources you can google related to best practices for this. I'd suggest you spend some time reading.
But since you asked... below is how you would do it for your example. If you do not define your class above the main, the compiler will complain because it won't know what a "MainWindow" is.
#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private slots:
void handleButton();
private:
QPushButton *m_button;
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.showMaximized();
return app.exec();
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Create the button, make "this" the parent
m_button = new QPushButton("My Button", this);
// set size and location of the button
m_button->setGeometry(QRect(QPoint(100, 100),
QSize(200, 50)));
// Connect button signal to appropriate slot
connect(m_button, SIGNAL(released()), this, SLOT(handleButton()));
}
void MainWindow::handleButton()
{
// change the text
m_button->setText("Example");
// resize button
m_button->resize(100,100);
}
#include essentially takes the contents of whatever file you choose and copy/pastes it at that location. The compiler then starts at the top of the file and works its way down to the bottom.
Knowing that, you should be able to just copy-paste the contents of the files in the order they are included.
mainwindow.h
mainwindow.cpp
main.cpp
The short answer is don't do this, you should define a class in its own header file and #include it to the main when you want to run it in the main. This allows you to reuse the class as you see fit throughout the program, its one of the tenets of Object Oriented programming, reusable code. For example
class A
{
public:
A();
~A();
void somePublicMethod();
private:
void somePrivateMethod();
};
If you include that class in your main when you compile that class to object code(assuming you know about implementing that class in a .cpp file) then when all the object files are linked to create the program the linker basically makes one big file with all the object code included in file to be fully compiled. I suggest you read up more on compiling and linking, essentially it boils down to three phases, preprocessing, compiling and linking. Learn more about Object Oriented programming and read up why it's a bad idea to just shove them all into one file. Every class should be in its own self contained .h file(unless its a tightly coupled class) so you can include them as you see fit. Hope this helps, have fun with Qt :)

getting the plain C++ implementation of a QT code

I was trying to figure out how this code will loke like in plain C++ without any dependency so I was using the moc compiler but apparently I'm wrong.
moc always returns
main.cpp:0: Note: No relevant classes found. No output generated.
the code is
#include <QApplication>
#include <QWidget>
#include <QPushButton>
class MyButton : public QWidget
{
public:
MyButton(QWidget *parent = 0);
};
MyButton::MyButton(QWidget *parent)
: QWidget(parent)
{
QPushButton *quit = new QPushButton("Quit", this);
quit->setGeometry(50, 40, 75, 30);
connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyButton window;
window.resize(250, 150);
window.move(300, 300);
window.setWindowTitle("button");
window.show();
return app.exec();
}
from http://www.zetcode.com/gui/qt4/firstprograms/
In general terms I'm interested in creating my own signal slot system using only the C++ standard library ( no boost signal, no QT, no nothing else ) so I'm doing this for research purpose and I'm only interested on the infrastructure about signals and slots.
Thanks.
Add the Q_OBJECT macro to the private section of your class, so moc converts it.
class MyButton : public QWidget
{
Q_OBJECT
public:
MyButton(QWidget *parent = 0);
};
Here is what the documentation says.