QObject::connect: No such slot mywindow::changerLargeur(int) - c++

i read other questions about the same issue but wasn't able to solve mine. When i run my code, the program starts, send QObject::connect: No such slot mywindow::changerLargeur(int) and then fails.
thanks you for your help
h file
#ifndef MYWINDOW_H
#define MYWINDOW_H
#include <QWidget>
#include <QSlider>
#include <QLCDNumber>
class mywindow : public QWidget
{
Q_OBJECT
public:
mywindow();
public slots:
void changerlargeur(int largeur);
private:
QSlider *glisseur;
QLCDNumber *afficheur;
};
#endif // MYWINDOW_H
cpp file
#include "mywindow.h"
mywindow::mywindow(): QWidget()
{
setFixedSize(200, 100);
glisseur = new QSlider(Qt::Horizontal,this);
glisseur->setRange(100,900);
glisseur->setGeometry(10, 60, 150, 20);
QObject::connect(glisseur, SIGNAL(valueChanged(int)), this, SLOT(changerLargeur(int)));
QObject::connect(glisseur, SIGNAL(valueChanged(int)), afficheur, SLOT(display(int)));
afficheur = new QLCDNumber(this);
afficheur->setSegmentStyle(QLCDNumber::Flat);
}
void mywindow::changerlargeur(intlargeur)
{
setFixedSize(largeur, 100);
}
main file
#include <QApplication>
#include "mywindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
mywindow fenetrep;
fenetrep.show();
return app.exec();
}

Like most other things in C++, Qt's signals and slots are case sensitive. So this won't work:
void changerlargeur(int largeur);
vs.
SLOT(changerLargeur(int))
You need to decide whether you want the L to be upper or lower case and stick with it.
Another issue is this:
QObject::connect(glisseur, SIGNAL(valueChanged(int)), afficheur, SLOT(display(int)));
afficheur = new QLCDNumber(this);
You can't connect to a slot on an object that doesn't exist yet.

Related

Qt Slot is not called when it lives on a thread created via std::async

I wanted to create a Qt widget which communicates with other classes on different threads via the signal / slot system. The recieving Objects are created in a Function wich is run via std::async.
The problem is: If the widget emits a signal the slot on the other thread is not called.
My Example:
I created the Class MainWindow which derives from QMainWindow and will live on the main thread. The class Reciever is created in a function which is called via std::async, and has a thread which should print something to the console.
I tested if the signal is emitted by connecting it to another slot on the same thread which works fine.
MainWindow.hpp
#pragma once
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
signals:
void send();
private slots:
void buttonClicked();
void recieve();
};
MainWindow.cpp
#include "MainWindow.hpp"
#include <iostream>
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
QPushButton* start = new QPushButton("Start");
setCentralWidget(start);
start->show();
connect(start, SIGNAL(clicked(bool)), this, SLOT(buttonClicked()));
connect(this, SIGNAL(send()), this, SLOT(recieve()));
}
void MainWindow::buttonClicked()
{
std::cout << "MainWindow::buttonClicked()\n";
emit send();
}
void MainWindow::recieve()
{
std::cout << "MainWindow::recieve()\n";
}
Reciever.hpp
#include <QObject>
class Reciever : public QObject
{
Q_OBJECT
public:
Reciever(QObject *parent = 0);
public slots:
void recieve();
};
Reciever.cpp
#include "Reciever.hpp"
#include <iostream>
Reciever::Reciever(QObject *parent) : QObject(parent)
{
std::cout << "Reciever()" << std::endl;
}
void Reciever::recieve()
{
std::cout << "Reciever::recieve()" << std::endl;
}
main.cpp
#include "MainWindow.hpp"
#include "Reciever.hpp"
#include <QApplication>
#include <future>
void StartAndConnect(MainWindow &widget)
{
Reciever* rec = new Reciever();
QObject::connect(&widget, SIGNAL(send()), rec, SLOT(recieve()));
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow myWidget;
myWidget.show();
auto future = std::async(std::launch::async, [&myWidget](){
StartAndConnect(myWidget);
});
app.exec();
future.wait();
}
After some research my strongest guess was, that the thread launched by std::async does not has a Qt event-loop and thus will not come to a point where the posted event (emit) is processed. I changed the main to use QtConcurrent::run but it also did not work.
EDIT
Here my try with QtConcurrent:
main2.cpp
#include "MainWindow.hpp"
#include "Reciever.hpp"
#include <QApplication>
#include <future>
#include <QtConcurrent>
void StartAndConnect(MainWindow &widget)
{
Reciever* rec = new Reciever();
QObject::connect(&widget, SIGNAL(send()), rec, SLOT(recieve()));
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow myWidget;
myWidget.show();
auto future = QtConcurrent::run( [&myWidget](){
StartAndConnect(myWidget);
});
app.exec();
future.waitForFinished();
}
You need a running event loop in your thread, if you want to process cross-thread slot calls.
auto future = QtConcurrent::run( [&myWidget](){
StartAndConnect(myWidget);
QEventLoop e;
e.exec();
});
But I recomend to use QThread, because in your case it is obvious. Qt has a very good documentation, that describes your case.

QTimer doesn't trigger

I'm trying to get the QTimer running, but it never triggers.
I found some other questions about the timer, but the problem was always the timer being out of scope. This is not the case in my small example:
I create the timer in a custom QMainWindow, this is the .h file:
#include <iostream>
#include <QtWidgets/QMainWindow>
#include <QTimer>
class MyMainWindow : public QMainWindow {
Q_OBJECT;
private:
QTimer *mainTimer;
public slots:
void timerUpdate();
public:
MyMainWindow();
};
This is the .cpp file:
#include "MyMainWindow.h"
MyMainWindow::MyMainWindow() {
QMainWindow();
mainTimer = new QTimer(this);
connect(mainTimer, SIGNAL(timeout()), this, SLOT(update()));
mainTimer->start(1000);
std::cout << "Timer created.\n";
}
void MyMainWindow::timerUpdate() {
std::cout << "test";
}
Finally, this is my main.cpp:
#include <QtWidgets/QApplication>
#include "MyMainWindow.h"
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
MyMainWindow mmw;
mmw.show();
return app.exec();
}
When I execute this code, I only get "Timer created." and never "test".
Any suggestions?
You're connecting to SLOT(update()), but your function is called timerUpdate.
Using more modern Qt 5 signal-slot connection syntax, that would never have happened and you'd get an error at compile-time. You should prefer using that.

QT connect crash using signal accepted

I have a problem with my Qt code. I wanted to write an program which are taking a coordinates of point and then that point is drawing in point with that coordinates. My program doesn't have any errors or warnings when i built it but it's crashing at start(MainWindow doesn't show). This is my code:
main.cpp
#include < QApplication >
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow win;
win.show();
return app.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QWidget>
#include <QAction>
#include <QToolBar>
#include <QTextCodec>
#include <QObject>
#include <QDialog>
#include <QLineEdit>
#include <QPushButton>
#include <QString>
#include "addpoint.h"
class MainWindow: public QMainWindow
{
Q_OBJECT
private:
QToolBar *AddToolbar;
QAction *AddPointAction;
AddPoint *AddPointDialog;
QLineEdit *x;
public:
MainWindow();
void createToolbar();
void createActionAdd();
signals:
public slots:
void PointClicked();
void DialogAccepted();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow()
{
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
createActionAdd();
createToolbar();
connect(AddPointAction, SIGNAL(triggered(bool)), this, SLOT(PointClicked()));
connect(AddPointDialog, SIGNAL(accepted()), this, SLOT(DialogAccepted()));
setMinimumSize(480, 320);
}
/**/
void MainWindow::createToolbar()
{
AddToolbar = new QToolBar;
AddToolbar->addAction(AddPointAction);
addToolBar(AddToolbar);
}
/**/
void MainWindow::createActionAdd()
{
AddPointAction = new QAction("Add Road", this);
x = new QLineEdit(this);
x->setFixedSize(100, 30);
x->move(100, 100);
}
/**/
void MainWindow::PointClicked()
{
AddPointDialog = new AddPoint(this);
AddPointDialog->setModal(true);
AddPointDialog->exec();
}
/**/
void MainWindow::DialogAccepted()
{
x->setText("abc");
}
addpoint.h
#ifndef ADDPOINT_H
#define ADDPOINT_H
#include <QWidget>
#include <QTextCodec>
#include <QDialog>
#include <QObject>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QString>
class AddPoint : public QDialog
{
Q_OBJECT
private:
QLabel *XpointL;
QLineEdit *XPoint;
QPushButton *OKButton;
public:
AddPoint(QWidget *parent);
void createButton();
signals:
public slots:
};
#endif // ADDPOINT_H
addpoint.cpp
#include "addpoint.h"
AddPoint::AddPoint(QWidget *parent) :QDialog(parent)
{
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
createButton();
connect(OKButton, SIGNAL(clicked(bool)), this, SLOT(accept()));
setMinimumSize(320, 240);
}
/**/
void AddPoint::createButton()
{
XpointL = new QLabel("Point X:", this);
XpointL->setFixedSize(100, 30);
XpointL->move(10, 10);
XPoint = new QLineEdit(this);
XPoint->setFixedSize(180, 30);
XPoint->move(120, 10);
OKButton = new QPushButton("OK", this);
OKButton->setFixedSize(100, 30);
OKButton->move(200, 150);
}
After running the program i see in aplication output lap:
"The program has unexpectedly finished."
"C:\QT\build-xxx-Desktop_Qt_5_4_2_MSVC2013_64bit-Debug\debug\xx.exe crashed"
I note that i made some experiments with this code and i saw that i have problem with signal accpeted() at mainwindow.cpp. I don't know what can i do with this problem. I hope you will help me.
AddPointDialog is uninitialized pointer, it does not yet point to valid AddPoint in MainWindow's constructor. You cannot call connect on that. Its value will change later, when you do AddPointDialog = new AddPoint(this); and only then will you be able to call connect.
Simply, you should move your connect call to void MainWindow::PointClicked() after you've initialized your pointer. I'd also make AddPointDialog local to that function and store it on the stack (you don't use it anywhere else and you're leaking memory).
The code would be:
void MainWindow::PointClicked()
{
AddPoint AddPointDialog(this);
AddPointDialog.setModal(true);
connect(&AddPointDialog, SIGNAL(accepted()), this, SLOT(DialogAccepted()));
AddPointDialog.exec();
}

Unable to connect signal to a function inside main()

I am aware that to use the signals and slots mechanism of Qt inside a class, the class must include the Q_OBJECT macro, but I am attempting to use signals and slots in main(), without using any class.
Here is my code so far:
#include <QApplication>
#include <QWidget>
#include <QTextEdit>
#include <QtGui>
void saveText();
int main(int argv, char **args)
{
QApplication app(argv, args);
QTextEdit textEdit;
QPushButton saveButton("Save!");
QPushButton exitButton("Exit!");
QObject::connect(&exitButton,SIGNAL(clicked()),qApp,SLOT(quit()));
QObject::connect(&saveButton,SIGNAL(clicked()),qApp,SLOT(saveText()));
QVBoxLayout vlyt;
vlyt.addWidget(&textEdit);
vlyt.addWidget(&exitButton);
vlyt.addWidget(&saveButton);
QWidget mainWindow;
mainWindow.setLayout(&vlyt);
mainWindow.show();
return app.exec();
}
void saveText()
{
exit(0);
}
Here is the GUI window generated:
From the above code, the exit button is connected to quit(), which is a Qt function, when clicked it works. The save button assigned to the function saveText(), is configured to exit, but does not do so.
Please tell me where I have gone wrong in understanding signals and slots in Qt.
Qt4...
All classes that inherit from QObject or one of its subclasses (e.g.,
QWidget) can contain signals and slots.1
So, you can not use slots where placed outside of QObject children.
You can connect signals to the slots which are in classes where derived from QObject. Put your slot in a class which is in a separated .h/.cpp file:
class MyClass : public QObject
{
Q_OBJECT
...
public slots:
void saveText();
};
According to Qt5: New Signal Slot Syntax in Qt 5. You can connect to those type of global functions. (Thanks to #thuga's comments)
I'll just put example here.
main.cpp:
#include <QCoreApplication>
#include <iostream>
#include <QObject>
#include "siggen.h"
void handler(int val){
std::cout << "got signal: " << val << std::endl;
}
int main(int argc, char *argv[])
{
SigGen siggen;
QObject::connect(&siggen, &SigGen::sgAction, handler);
siggen.action();
QCoreApplication a(argc, argv);
std::cout << "main prog start" << std::endl;
return a.exec();
}
siggen.h:
#ifndef SIGGEN_H
#define SIGGEN_H
#include <QObject>
class SigGen : public QObject
{
Q_OBJECT
public:
explicit SigGen(QObject *parent = 0);
void action(void);
signals:
void sgAction(int value);
};
#endif // SIGGEN_H
siggen.cpp:
#include "siggen.h"
SigGen::SigGen(QObject *parent) : QObject(parent)
{}
void SigGen::action()
{
emit sgAction(42);
}
QObject::connect(&saveButton, &QPushButton::clicked, [](){saveText();}); // qt5.9.6
or as mentioned in the masoud's answer
QObject::connect(&saveButton, &QPushButton::clicked, saveText); // qt5.9.6
It is possible to connect a signal to function inside main function.
This has been tested in Qt5.15. Here is the simple example where the QPushButton 'Clicked' signal is used to trigger a function (here I used lamda's, but regular functions can also be used).
int main(int argc, char *argv[])
{
// Created QApplication
QApplication a(argc, argv);
// Created the splashscreen(which is QObject)
QPixmap pixmap(":/images/Sample.png");
QSplashScreen splash(pixmap);
// Created the pushbutton and added to splashscreen
QPushButton b(&splash);
b.setGeometry(50,50, 100, 50);
b.setText("FPS");
// variable to be modified inside a lamda function
int i = 0;
// Connection for button clicked signal executes lamda function
QObject::connect(&b, &QPushButton::clicked,
[i = static_cast<const int&>(i), &splash = static_cast<QSplashScreen&>(splash)]()mutable
{i = i+1; splash.showMessage("clicked: "+ QString::number(i));});
// Adding properties and displaying the splashscreen
splash.setGeometry(0,0, 1920, 1080);
splash.setEnabled(true);
splash.show();
a.processEvents();
return a.exec();
}

Open external links from flash player hosted on QWebKit

i have flash player running on QWebkit , and on the flash player there are some web links
that needs to be open in external browser , what i did is :
m_webView->page()->setLinkDelegationPolicy(QWebPage::LinkDelegationPolicy::DelegateAllLinks);
connect(m_webView->page(),SIGNAL(linkClicked(const QUrl&)),
this,
SLOT(linkClickedHandler(const QUrl&)),Qt::DirectConnection);
void WebBroswerDeleget::linkClickedHandler(const QUrl& url)
{
QDesktopServices::openUrl(QUrl(url.toString(), QUrl::TolerantMode));
}
but its never triggered even of i change in the connect from m_webView->page() to m_webView
i overrided the QWebview::createWindow like this:
QWebView* MyAdWebview::createWindow (QWebPage::WebWindowType type)
{
QWebView* p = new QWebView(0);
connect(p->page()->networkAccessManager(), SIGNAL(finished(QNetworkReply*)), this, SLOT(newWindowLoadFinished(QNetworkReply*)), Qt::UniqueConnection);
return p;
}
void MyAdWebview::newWindowLoadFinished(QNetworkReply* reply) {
QDesktopServices::openUrl(reply->url().toString());
}
QDesktopServices::openUrl is a cutom function which opens the default system browser with this url
This is working for me on both 4.7.2 QtEmbedded and 4.8.1 on mac. What I don't understand is this:
m_webView->page()->setLinkDelegationPolicy(QWebPage::LinkDelegationPolicy::DelegateAllLinks);
Just do:
m_webView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
Something like this works for me:
#include <QWebPage>
#include <QWebView>
#include <QApplication>
#include "sigrec.h"
int main(int argc, char** argv)
{
QApplication a(argc, argv);
SigRec rec;
QWebView view;
view.page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
QObject::connect(view.page(), SIGNAL(linkClicked(const QUrl&)), &rec, SLOT(onLinkClicked(const QUrl&)),
Qt::DirectConnection);
view.show();
view.setUrl(QUrl("http://www.google.com"));
return a.exec();
}
Where SigRec is something like this:
#ifndef SIGREC_H
#define SIGREC_H
#include <QObject>
#include <QUrl>
class SigRec : public QObject
{
Q_OBJECT
public:
explicit SigRec(QObject *parent = 0);
public slots:
void onLinkClicked(const QUrl &url);
};
#endif // SIGREC_H