I am following the Qt example listed in the QtSDK titled: "Getting Started Programming with Qt". My problem is that the program doesn't display any of the objects.
My main.cpp looks like so:
#include <QtGui>
#include <notepad.h>
int main(int argv, char **args) {
QApplication app(argv, args);
QVBoxLayout layout;
Notepad notepad();
QWidget window;
window.setLayout(&layout);
window.show();
return app.exec();
}
The 'notepad.h' file:
#ifndef NOTEPAD_H
#define NOTEPAD_H
#include <QtGui>
class Notepad : public QMainWindow {
Q_OBJECT
public:
Notepad();
private slots:
void open();
void save();
void quit();
private:
QTextEdit *text_edit;
QAction *open_action;
QAction *save_action;
QAction *exit_action;
QMenu *file_menu;
};
#endif // NOTEPAD_H
The 'notepad.cpp' file:
#include "notepad.h"
Notepad::Notepad() {
open_action = new QAction(tr("&Open"), this);
save_action = new QAction(tr("&Save"), this);
exit_action = new QAction(tr("&Exit"), this);
connect(open_action, SIGNAL(triggered()), this, SLOT(open()));
connect(save_action, SIGNAL(triggered()), this, SLOT(save()));
connect(exit_action, SIGNAL(triggered()), qApp, SLOT(quit()));
file_menu = menuBar()->addMenu(tr("&File"));
file_menu->addAction(open_action);
file_menu->addAction(save_action);
file_menu->addSeparator();
file_menu->addAction(exit_action);
text_edit = new QTextEdit;
setCentralWidget(text_edit);
setWindowTitle(tr("Notepad"));
}
void Notepad::open() {
...
}
void Notepad::save() {
...
}
void Notepad::quit() {
}
Any help in resolving the matter would be much appreciated.
Edit
My original question asked why I was I was getting a compile time error for not implementing the "quit" function incase you are wondering :).
You have to implement quit() method defined as private slot in notepad.h . Unresolved errors are linking errors and tells you that linker hasn't found any implementation for the function declaration. Add this to notepad.cpp :
void Notepad::quit() {
...
}
For new question :
Try notepad.show(). Your MainWindow can be notepad object because it is a QMainWindow.
int main(int argv, char **args) {
QApplication app(argv, args);
Notepad notepad();
notepad.show();
return app.exec();
}
Related
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
I am having difficulty in my Qt program with connecting button signals to my slots. My code is:
Main.cpp
#include <QtGui/QApplication>
#include "MainWidget.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWidget mainWidget;
mainWidget.show();
return app.exec();
}
MainWidget.h
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
class MainWidget : public QWidget
{
public:
MainWidget();
public slots:
void bAdvice_clicked();
void bWeather_clicked();
void bNextMeeting_clicked();
void bQuit_clicked();
};
#endif // MAINWIDGET_H
MainWidget.cpp
#include "MainWidget.h"
#include <QMessageBox>
#include <QPushButton>
#include <QTextEdit>
#include <QVBoxLayout>
MainWidget::MainWidget()
{
QLayout *layout = new QVBoxLayout();
this->setLayout(layout);
QTextEdit *message = new QTextEdit();
layout->addWidget(message);
QPushButton *bAdvice = new QPushButton("Advice");
connect(bAdvice, SIGNAL(clicked()), this, SLOT(bAdvice_clicked()));
layout->addWidget(bAdvice);
QPushButton *bWeather = new QPushButton("Weather");
connect(bWeather, SIGNAL(clicked()), this, SLOT(bWeather_clicked()));
layout->addWidget(bWeather);
QPushButton *bNextMeeting = new QPushButton("Next Meeting");
connect(bNextMeeting, SIGNAL(clicked()), this, SLOT(bNextMeeting_clicked()));
layout->addWidget(bNextMeeting);
QPushButton *bQuit = new QPushButton("Quit");
connect(bQuit, SIGNAL(clicked()), this, SLOT(bQuit_clicked()));
layout->addWidget(bQuit);
}
void MainWidget::bAdvice_clicked()
{
}
void MainWidget::bWeather_clicked()
{
}
void MainWidget::bNextMeeting_clicked()
{
QMessageBox::information(this, "Next Meeting", "Today", QMessageBox::Ok);
}
void MainWidget::bQuit_clicked()
{
this->close();
}
The program outputs the following:
Starting C:\Users\Sameer\Documents\PartAQuestion2\debug\PartAQuestion2.exe...
Object::connect: No such slot QWidget::bAdvice_clicked() in MainWidget.cpp:16
Object::connect: No such slot QWidget::bWeather_clicked() in MainWidget.cpp:20
Object::connect: No such slot QWidget::bNextMeeting_clicked() in MainWidget.cpp:24
Object::connect: No such slot QWidget::bQuit_clicked() in MainWidget.cpp:28
C:\Users\Sameer\Documents\PartAQuestion2\debug\PartAQuestion2.exe exited with code 0
The code seems right, no compiler warnings. Just this output at runtime. But it looks like I hooked the signals and slots up correctly.
Add Q_OBJECT to your class, like this:
class MainWidget : public QWidget
{
Q_OBJECT
You also have to run moc to generate some helper code. qmake does that automatically for your, but if you compile this yourself, you need to run moc.
When I started with Qt, I had this problem a lot. As I see it your slots are defined wrong. If you look at the signature for the signal (Qt Clicked Signal Docs), you will see that the argument list is (bool clicked = false).
The way Qt's signal & slots connect work at run time, is that it will only connect the signal and slot if they have the exact same signatures. If they don't match exactly, no connection.
so in MainWidget.h
public slots:
void bAdvice_clicked(bool);
In MainWidget.cpp
connect(bAdvice, SIGNAL(clicked(bool)), this, SLOT(bAdvice_clicked(bool)));
Things will start working for you.
Edited:
Compiled your code and all the slots were correctly called.
It was just the Q_OBJECT macro that was missing.
In a program which calculates abritary precision numbers.
I have an action on the taskbar.
QAction* button_stop_continue.
I've set the icon green icon in the beginning of the program, when calculations are being executed it should turn red and so on.
I've already tried something like this:
connect(this, SIGNAL(startedComputing()), this, SLOT(turnIconRed()));
connect(this, SIGNAL(finishedComputing()), this, SLOT(turnIconGreen()));
the function turnIconRed is looking similar to this:
void turnIconRed()
{
button_stop_continue->setIcon(QIcon("images/red-light.png"));
}
I've come up with some incredibly-ugly algorithms :S. Isn't there a straight-forward way to deal with that on Qt? Any ideas?
Thanks.
I would subclass QAction and add some logic for the states in which it can be. It is never a good idea to hardcode the color of something into the name of a method. By subclassing QAction, the look and feel of it is encapsulated.
This could be something like this:
Header file:
class StateAction : public QAction
{
Q_OBJECT
public:
explicit StateAction(QObject *parent = 0);
public slots:
void start();
void stop();
void pause();
};
Implementation file:
StateAction::StateAction(QObject *parent) :
QAction(parent)
{
this->stop();
}
void StateAction::start()
{
this->setIcon(QIcon(":/states/start.png"));
}
void StateAction::stop()
{
this->setIcon(QIcon(":/states/stop.png"));
}
void StateAction::pause()
{
this->setIcon(QIcon(":/states/pause.png"));
}
Now, in your MainWindow you can use that custom QAction simply by connecting its slots to the right signals:
Header file:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void startedComputing();
void finishedComputing();
void pausedComputing();
private:
void createActions();
void createToolbars();
void createConnections();
StateAction *m_stateAction;
};
Implementation file:
...
void MainWindow::createConnections()
{
connect(this, SIGNAL(startedComputing()), m_stateAction, SLOT(start()));
connect(this, SIGNAL(finishedComputing()), m_stateAction, SLOT(stop()));
connect(this, SIGNAL(pausedComputing()), m_stateAction, SLOT(pause()));
}
I've found a solution using QToolButton here it is:
Header : FenPrincipale.h
#ifndef FENPRINCIPALE_H
#define FENPRINCIPALE_H
#include <QWidget>
#include <QVBoxLayout>
#include <QToolButton>
#include <QToolBar>
#include <QAction>
#include <QTextEdit>
class FenPrincipale : public QWidget {
Q_OBJECT
public:
FenPrincipale();
private slots:
void goComputing();
void stopComputing();
private:
QAction* actionDemarrer; // Start computing
QAction* actionArreter; // Stop computing
QToolBar* toolBarActions;
QToolButton* boutonAction; // this button holds the appropriate action
QVBoxLayout* layoutPrincipale;
QTextEdit* resultat; // show result
};
...
Implementation : FenPrincipale.cpp
#include "FenPrincipale.h"
FenPrincipale::FenPrincipale() : QWidget()
{
this->setFixedSize(400, 200);
// create actions
actionDemarrer = new QAction(QIcon("bouton-vert.png"), "demarrer", this);
actionArreter = new QAction(QIcon("bouton-rouge.png"), "arreter", this);
boutonAction = new QToolButton;
boutonAction->setDefaultAction(actionDemarrer);
// create toolbar
toolBarActions = new QToolBar(this);
toolBarActions->addWidget(boutonAction);
// create result widget
resultat = new QTextEdit(this);
// create layout
layoutPrincipale = new QVBoxLayout(this);
layoutPrincipale->addWidget(toolBarActions);
layoutPrincipale->addWidget(resultat);
this->setLayout(layoutPrincipale);
// make connections
QObject::connect(actionDemarrer, SIGNAL(triggered()), this, SLOT(goComputing()));
QObject::connect(actionArreter, SIGNAL(triggered()), this, SLOT(stopComputing()));
}
void FenPrincipale::goComputing()
{
resultat->setText("Computing...");
boutonAction->setDefaultAction(actionArreter);
}
void FenPrincipale::stopComputing()
{
resultat->setText("Partial result : {?}");
boutonAction->setDefaultAction(actionDemarrer);
}
...
Main
#include <QApplication>
#include "FenPrincipale.h"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
FenPrincipale fenetre;
fenetre.show();
return app.exec();
}
main.cpp
#include <QtGui>
#include <QApplication>
int main(int argv, char **args)
{
QApplication app(argv, args);
QTextEdit textEdit;
QPushButton quitButton("Quit");
QObject::connect(&quitButton, SIGNAL(clicked()), qApp, SLOT(quit()));
QVBoxLayout layout;
layout.addWidget(&textEdit);
layout.addWidget(&quitButton);
QWidget window;
window.setLayout(&layout);
window.show();
return app.exec();
}
notepad.cpp
#include <QtGui>
#include <QApplication>
class Notepad : public QMainWindow
{
Notepad::Notepad()
{
saveAction = new QAction(tr("&Open"), this);
saveAction = new QAction(tr("&Save"), this);
exitAction = new QAction(tr("E&xit"), this);
connect(openAction, SIGNAL(triggered()), this, SLOT(open()));
connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));
connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(openAction);
fileMenu->addAction(saveAction);
fileMenu->addSeparator();
fileMenu->addAction(exitAction);
textEdit = new QTextEdit;
setCentralWidget(textEdit);
setWindowTitle(tr("Notepad"));
}
Q_OBJECT
public:
Notepad();
private slots:
void open();
void save();
void quit();
private:
QTextEdit *textEdit;
QAction *openAction;
QAction *saveAction;
QAction *exitAction;
QMenu *fileMenu;
};
ERRORS:
extra qualification 'NotePad::' on Member Notepad (Line 8)
notepad::notepad() cannot be overloaded (Line 32)
with notepad::notepad (line 8)
Why am I getting these errors? The constructor looks fine and the class setup looks fine. But I am getting these errors.
The Notepad:: in front of your Notepad() constructor inside the Notepad class is not necessary. Neither is the later declaration, because you have done this and defined it (although privately) above. You might want to consider separating it into a header and cpp file.
There are still various other issues with the code as you have posted, but the errors you posted are most likely caused by what I mentioned above.
You have qualified the inline private constructor with Notepad::
You have then incorrectly overloaded that private constructor as public in a second declaration
Q_OBJECT macro needs to be first in the class declaration before methods and members.
You have at least 4 memory leaks for each instance of Notepad?
etc
Perhaps pick up a book?
I am having difficulty in my Qt program with connecting button signals to my slots. My code is:
Main.cpp
#include <QtGui/QApplication>
#include "MainWidget.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWidget mainWidget;
mainWidget.show();
return app.exec();
}
MainWidget.h
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
class MainWidget : public QWidget
{
public:
MainWidget();
public slots:
void bAdvice_clicked();
void bWeather_clicked();
void bNextMeeting_clicked();
void bQuit_clicked();
};
#endif // MAINWIDGET_H
MainWidget.cpp
#include "MainWidget.h"
#include <QMessageBox>
#include <QPushButton>
#include <QTextEdit>
#include <QVBoxLayout>
MainWidget::MainWidget()
{
QLayout *layout = new QVBoxLayout();
this->setLayout(layout);
QTextEdit *message = new QTextEdit();
layout->addWidget(message);
QPushButton *bAdvice = new QPushButton("Advice");
connect(bAdvice, SIGNAL(clicked()), this, SLOT(bAdvice_clicked()));
layout->addWidget(bAdvice);
QPushButton *bWeather = new QPushButton("Weather");
connect(bWeather, SIGNAL(clicked()), this, SLOT(bWeather_clicked()));
layout->addWidget(bWeather);
QPushButton *bNextMeeting = new QPushButton("Next Meeting");
connect(bNextMeeting, SIGNAL(clicked()), this, SLOT(bNextMeeting_clicked()));
layout->addWidget(bNextMeeting);
QPushButton *bQuit = new QPushButton("Quit");
connect(bQuit, SIGNAL(clicked()), this, SLOT(bQuit_clicked()));
layout->addWidget(bQuit);
}
void MainWidget::bAdvice_clicked()
{
}
void MainWidget::bWeather_clicked()
{
}
void MainWidget::bNextMeeting_clicked()
{
QMessageBox::information(this, "Next Meeting", "Today", QMessageBox::Ok);
}
void MainWidget::bQuit_clicked()
{
this->close();
}
The program outputs the following:
Starting C:\Users\Sameer\Documents\PartAQuestion2\debug\PartAQuestion2.exe...
Object::connect: No such slot QWidget::bAdvice_clicked() in MainWidget.cpp:16
Object::connect: No such slot QWidget::bWeather_clicked() in MainWidget.cpp:20
Object::connect: No such slot QWidget::bNextMeeting_clicked() in MainWidget.cpp:24
Object::connect: No such slot QWidget::bQuit_clicked() in MainWidget.cpp:28
C:\Users\Sameer\Documents\PartAQuestion2\debug\PartAQuestion2.exe exited with code 0
The code seems right, no compiler warnings. Just this output at runtime. But it looks like I hooked the signals and slots up correctly.
Add Q_OBJECT to your class, like this:
class MainWidget : public QWidget
{
Q_OBJECT
You also have to run moc to generate some helper code. qmake does that automatically for your, but if you compile this yourself, you need to run moc.
When I started with Qt, I had this problem a lot. As I see it your slots are defined wrong. If you look at the signature for the signal (Qt Clicked Signal Docs), you will see that the argument list is (bool clicked = false).
The way Qt's signal & slots connect work at run time, is that it will only connect the signal and slot if they have the exact same signatures. If they don't match exactly, no connection.
so in MainWidget.h
public slots:
void bAdvice_clicked(bool);
In MainWidget.cpp
connect(bAdvice, SIGNAL(clicked(bool)), this, SLOT(bAdvice_clicked(bool)));
Things will start working for you.
Edited:
Compiled your code and all the slots were correctly called.
It was just the Q_OBJECT macro that was missing.