connect() can't find signal function - c++

I'm trying to set the connect() like this:
QObject::connect(&webControl,
SIGNAL(Ui::MainWindow::loadFinished(bool)),
&w,
SLOT(Ui::MainWindow::loadFinished(bool)));
in main() function but it give the error:
QObject::connect: No such signal
QWebView::Ui::MainWindow::loadFinished(bool)
w and webControl are declared like this:
MainWindow w;
QWebView webControl;
And here's my files:
mainWindow.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void loadFinished(bool arg1);
private:
Ui::MainWindow *ui;
};
mainWindow.cpp
void MainWindow::loadFinished(bool arg1)
{
}
Why I'm getting this error and how do I fix this?

You need to add QWebView *webView; to your mainwindow.h:
mainwindow.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QWebView *getWebView() const;
public slots:
void loadFinished(bool arg1);
void setWebView(QWebView *webControl);
private:
Ui::MainWindow *ui;
QWebView *webView;
};
mainwindow.cpp
...
QWebView *MainWindow::getWebView() const
{
return webView;
}
void MainWindow::setWebView(QWebView *webControl)
{
webView = webControl;
QObject::connect(webControl,
SIGNAL(loadFinished(bool)),
this,
SLOT(loadFinished(bool)));
}
If you really need declaration of QWebView in main.cpp then pass pointer to setWebView() function:
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
QWebView webControl;
w.setWebView(&webControl);
w.show();
return a.exec();
}

Your problem is that QWebView webControl; webcontrol is a qwebview and your signal is not in QWebview, but in MainWindow. You need that signal in QWebView. That is why its complaining about a signal that can't be found.
EDIT
You have a problem knowing what is a slot, and what a signal. Thy are two different things. A signal is like an alarm. An slot is the receiver and it works as a normal function.
If you want your webControl var to be the sender, then you have to declare the signal like this in y our QWebView.h class :
signals:
void yourSignalName(bool arg1);
and use the connect like this:
QObject::connect(&webControl,
SIGNAL(yourSignalName(bool)),
&w,
SLOT(loadFinished(bool)));

I'd suggest the new Qt5 syntax (which is optional):
QObject::connect(&webControl, &Ui::MainWindow::loadFinished,
&w, &Ui::MainWindow::loadFinished);
more on the new syntax: http://wiki.qt.io/New_Signal_Slot_Syntax

Related

How do I edit QMainWindow UI Widget From Another Class?

I need to edit a QLabel from MainWindow's UI in another source file. I've tried messing around with singals and slots, but honestly I'm completely lost and the Qt documentation doesn't help me in this exact situation. I understand that this has been asked in the past, but I have not found a solution that works for me. I'm new to Qt, and C++ in general.
I have the following code (greatly simplified):
"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();
void setFoo(char* text);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
"mainwindow.cpp"
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow) {
ui->setupUi(this);
this->statusBar()->setSizeGripEnabled(false);
}
MainWindow::~MainWindow() {
delete ui;
}
void MainWindow::setFoo(char* text) {
ui->fooLabel->setText(text);
}
"secondwindow.h"
#ifndef SECONDWINDOW_H
#define SECONDWINDOW_H
#include <QWidget>
namespace Ui {
class SecondWindow;
}
class SecondWindow: public QWidget {
Q_OBJECT
public:
explicit SecondWindow(QWidget *parent = 0);
~SecondWindow();
private:
Ui::SecondWindow*ui;
}
#endif // SecondWindow_H
"secondwindow.cpp"
#include "secondwinodw.h"
#include "ui_secondwinodw.h"
#include "mainwindow.h"
SecondWindow::SecondWindow(QWidget *parent) :
QWidget(parent),
ui(new Ui::SecondWindow) {
ui->setupUi(this);
}
SecondWindow::~SecondWindow() {
delete ui;
}
void SecondWindow::on_fooButton_clicked() {
MainWindow::setFoo("example");//The method is private so this is not possible, but this is my goal
}
When a user clicks on fooButton, I need to access and edit the MainWindow's UI QLabel(or a public method that does this).
The secondwindow is not being created in the main() function
void MainWindow::keyPressEvent(QKeyEvent *event) {
switch (event->key()) {
case Qt::Key_A:
if (event->modifiers()==Qt::ShiftModifier) {
SecondWindow*secwind= new SecondWindow();
secwind->show();
}
break;
}
}
In OOP the ones that interact are the objects, not the classes or the files, that is, the following expression:I need to edit QLabel from MainWindow's UI in another source file It does not make sense, what you should say is that an object of the MainWindow class is modified by another object of the SecondWindow class. The files do not make the program, the interaction between objects do it.
I'm assuming that both objects are created in the main.cpp:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w1;
SecondWindow w2;
w1.show();
w2.show();
return a.exec();
}
Now if I go to attack the main problem, Qt handles the concept of signals and slots, so we will use it, as the action to a SecondWindow object will cause the information to be sent, I will create a signal that carries that information:
secondwindow.h
#ifndef SECONDWINDOW_H
#define SECONDWINDOW_H
#include <QWidget>
namespace Ui {
class SecondWindow;
}
class SecondWindow: public QWidget {
Q_OBJECT
public:
explicit SecondWindow(QWidget *parent = 0);
~SecondWindow();
signals:
void messageChanged(const QString & message); // <---
private slots:
void void SecondWindow::on_fooButton_clicked();
private:
Ui::SecondWindow*ui;
}
#endif // SecondWindow_H
when the button is pressed, the signal with the information must be emitted
secondwindow.cpp
...
void SecondWindow::on_fooButton_clicked() {
emit messageChanged("example");//The method is private so this is not possible, but this is my goal
}
Now we go to the receiver's side, how will we get a slots, you have done it but do not use char *, that's C, we're using C++ and much better we're using Qt, it's best to use QString:
mainwindow.h
....
void setFoo(const QString & text);
mainwindow.cpp
...
void MainWindow::setFoo(const QString & text) {
ui->fooLabel->setText(text);
}
And finally we make the connections:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w1;
SecondWindow w2;
QObject::connect(&w2, &SecondWindow::messageChanged, &w1, &MainWindow::setFoo);
w1.show();
w2.show();
return a.exec();
}
update:
void MainWindow::keyPressEvent(QKeyEvent *event) {
switch (event->key()) {
case Qt::Key_A:
if (event->modifiers()==Qt::ShiftModifier) {
SecondWindow*secwind= new SecondWindow();
connect(secwind, &SecondWindow::messageChanged, this, &MainWindow::setFoo);
secwind->show();
}
break;
}
}

QObject::connect: No such signal(classname)(signalname)(atribure)

I have a problem. All is great when I compile, but slots don't work. After application starts, it outputs QObject::connect: No such signal CMatrix::ReadyToDraw(ww). I tested it, slot DrawFunction() doesn't work. I can't debug because of segmentation fault.
header.h
class CMatrix:public QObject
{
Q_OBJECT
public:
int **m_pMatrix;
const short int m_size=4;
public:
CMatrix();
bool checkFields();
void setField();
signals:
void ReadyToDraw(CMatrix *ww);
public slots:
void MoveDown();
void MoveTop();
void MoveLeft();
void MoveRight();
};
class MainWindow : public QWidget
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void DrawFunction(CMatrix *A);
public:
QPushButton* butTop;
QList<QLabel*> lblList;
};
main.cpp
#include "header.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
CMatrix *ww=new CMatrix;
QObject::connect(w.butTop,SIGNAL(clicked()),ww,SLOT(MoveTop()));
QObject::connect(ww,SIGNAL(ReadyToDraw(ww)),&w,SLOT(DrawFunction(ww)));
w.show();
return a.exec();
}
your signals signature is
ReadyToDraw(CMatrix *)
not
ReadyToDraw(ww)
as connect() needs the type, not the name of the variable.
so change your connect line to:
QObject::connect(ww,SIGNAL(ReadyToDraw(CMatrix *)),&w,SLOT(DrawFunction(CMatrix *)));

QT program crashes after connect()

I'm trying to write my new app, but it crashes every time I press a button on QDialog.
Here's my code :
mainwindow.h
#include <QMainWindow>
#include "creatlist.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QDialog* creatList;
public slots:
void tableFull(){
...some code here...
}
private:
Ui::MainWindow *ui;
};
creatlist.h :
#include <QDialog>
#include "mainwindow.h"
namespace Ui {
class creatlist;
}
class MainWindow;
class creatlist : public QDialog
{
Q_OBJECT
public:
explicit creatlist(QWidget *parent = 0);
~creatlist();
MainWindow* mainwindow;
signals:
void updateList();
public slots:
void ready(){
///////////////////////////////////////////////////////////crash
connect(this,SIGNAL(updateList()),mainwindow,SLOT(tableFull()));
emit updateList();
}
private:
Ui::creatlist *ui;
};
If i try to send some signals my app crashes with a Segmentation Fault.
I did:
void creatlist::ready()
{
mainwindow = new MainWindow(this);
emit mainwindow->linktableFull();
}
but if I try to do QTextBroser.append("hue hue"); in linktableFull(), QTextBrowser is always empty.
Your QTextBrowser always empty because you create new mainwindow object in every ready() function. You should create mainwindow object once and use same mainwindow object throughout code. You can create new mainwindow object in creatlist constructor.

Qt: Calling MainWindow::Ui from another class using signals and slots

I made a simple Qt project to cover the issue of calling Ui from another class.
The Files:
mainwindow.h | mainwindow.cpp | client.h | client.cpp | main.cpp
The Issue:
Connecting a signal from client.cpp to a slot in mainwindow.cpp worked very well.
But when I added a ui->statusBar->showMessage("message");
in the slot, it didn't work.
NOTE: When I made the signal and the slot both in mainwindow.cpp it worked, but calling a slot from mainwindow.cpp from a signal and connect() in client.cpp doesn't work.
The Codes: (trimmed to the essentials)
mainwindow.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
signals:
public slots:
void doSomething();
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
void MainWindow::doSomething()
{
QMessageBox::information(0, "test", "BINGO!!");
ui->statusBar->showMessage("testing");
}
client.h
class client : public QObject
{
Q_OBJECT
public:
explicit client(QObject *parent = 0);
void call();
signals:
void connected();
public slots:
};
client.cpp
client::client(QObject *parent) :
QObject(parent)
{
MainWindow main;
connect(this, SIGNAL(connected()), &main, SLOT(doSomething()));
call();
}
void client::call()
{
emit connected();
}
Added:
main.cpp
#include <QtGui/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Thanks.
client::client(QObject *parent) :
QObject(parent)
{
MainWindow main;
connect(this, SIGNAL(connected()), &main, SLOT(doSomething()));
call();
}
Your MainWindow lives on the stack. I think by the time your doSomething slot is triggered, the MainWindow object is already long gone. Try creating your MainWindow on the heap instead.
I see a major mistake in the code you have posted.
You have created an instance of MainWindow in the file main.cpp and thats the window you see when you run the application. But in your client.cpp you are creating a second instance of MainWindow and connecting the signal from the client object to the slot of the second MainWindow object you create. You are not seeing two main windows because you do not run the exec or show methods of this second instance.
Now coming to the solution, you will have to connect the signal from client to the proper MainWindow instance. I will suggest two methods below.
First:
I believe you create an instance of client in one of the member functions of the class MainWindow. If so then shift the connect method to the file mainwindow.cpp
Something like:
void MainWindow::someFunction()
{
client* c = new client();
connect(c, SIGNAL(connected()), this, SLOT(doSomething()));
c->call();
}
Second:
If you cannot do what is explained above, then you can use a combination of a static pointer and a static function to get the instance of MainWindow. Note that this method can also be used to ensure that there is only one instance of MainWindow at any given time.
mainwindow.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
signals:
public slots:
void doSomething();
public:
explicit MainWindow(QWidget* parent = 0);
~MainWindow();
static MainWindow* GetInstance(QWidget* parent = 0);
private:
Ui::MainWindow *ui;
static MainWindow* mainInstance;
};
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow* MainWindow::mainInstance = 0;
MainWindow* MainWindow::GetInstance(QWidget *parent)
{
if(mainInstance == NULL)
{
mainInstance = new MainWindow(parent);
}
return mainInstance;
}
void MainWindow::doSomething()
{
QMessageBox::information(0, "test", "BINGO!!");
ui->statusBar->showMessage("testing");
}
Now in whatever class you need to get the instance of MainWindow in use, simply use the static function MainWindow::GetInstance to get the pointer to the MainWindow instance and use that as the parameter for connect.
i.e.,
MainWindow* instance = MainWindow::GetInstance();
client* c = new client();
connect(c, SIGNAL(connected()), instance , SLOT(doSomething()));

Trouble connecting loadFinished SIGNAL to custom SLOT

I'm new to Qt, C++ and signals and slots. I'm trying to load in a webpage. Then set a label_3's text to the title of the webpage. To do this I figured I had to connect the loadFinished signal to my custom function. But I'm having trouble doing just that.
I've read up on the manual, different examples and other questions, but I'm stuck.
This is a excerpt from code I have so far.
How do I properly connect the signal loadFinished() to my function labelSetText()?
main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
void MainWindow::on_pushButton_clicked()
{
QString webAdress = ui->lineEdit->text();
QWebView *view = ui->webView;
view->load(QUrl(webAdress));
QString taxt = view->title();
connect(&view, SIGNAL(loadFinished(bool)),
this, SLOT(labelSetText(taxt)));
QWebPage * webPage = view->page();
}
void MainWindow::labelSetText(QString titleStr)
{
ui->label_3->setText(titleStr);
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QWidget>
namespace Ui {
class MainWindow;
}
class MainWindow : public QWidget
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
void labelSetText(QString titleStr);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
EDIT:
This is the error I get
E:\_Programming\C++\playAround\mainwindow.cpp:37: error: no matching function for call to 'MainWindow::connect(QWebView**, const char*, MainWindow* const, const char*)'
this, SLOT(labelSetText(taxt)));
^
That's not how connections work. A signal-slot connection can only pass data from the signal into the slot. It can't pass arbitrary variables like you do. The only way you could write your connect statement is as follows (the this argument is unnecessary):
connect(view, SIGNAL(loadFinished(bool)), SLOT(labelSetText(QString)));
This of course doesn't work, because the signal and slot are incompatible. You of course don't need the intermediate slot, since a label already has the slot you want, but it doesn't help:
connect(view, SIGNAL(loadFinished(bool)), ui->label_3, SLOT(setText(QString)));
Note that you should not have connect(&view, ... since view is already a pointer-to-QObject.
To do it, you need to leverage C++11:
connect(view, &QWebView::loadFinished, [=,this](){
this->ui->label_3->setText(taxt);
});
The lambda syntax translates into a functor class instance with copies of taxt and this as members. The compiler essentially creates the following, on the fly:
class Functor_1 {
MainWindow * _this;
QString taxt;
public:
MyFunctor_1(MainWindow * a1, const QString & a2) : _this(a1), taxt(a2) {}
void operator() {
_this->ui->label_3->setText(taxt);
}
}
...
connect(view, &QWebView::loadFinished, Functor_1(this, taxt));
Of course this means that if you want to use Qt 4 signals and slots, you need to add the taxt member to your MainWindow class, and create a slot to do what the functor does. So, for Qt 4:
class MainWindow : public QMainWindow {
Q_OBJECT
QString m_taxt;
Q_SLOT void loadFinished() {
ui->label_3->setText(m_taxt);
}
...
Q_SLOT void on_pushButton_clicked() {
QString webAdress = ui->lineEdit->text();
QWebView *view = ui->webView;
view->load(QUrl(webAdress));
m_taxt = view->title();
connect(view, SIGNAL(loadFinished(bool)), SLOT(loadFinished());
...
}
};
Note that you shouldn't be connecting repeatedly. For Qt 4 style connection, move the connect to MainWindow's constructor. For Qt 5 style connection, you need to break the connection once it fires.