i'm learning C++ and I run into a problem. I'm trying to make a simple web browser. It maybe because i use Class MainWindow in WebWiew. If i included MainWindow in WebWiew, the compiler says that the class MainWindow does not exist.
The problem occurs when I connect WebView with the interface.
I make a short version of my program.
webview.cpp:6: erreur : no matching function for call to 'WebView::connect(WebView* const, const char*, MainWindow*&, const char*)';
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtWebKitWidgets>
#include "webview.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
public slots:
void adressChanged(QUrl url);
void setTabTitle(QString title);
void setProgressionValue(int value);
};
#endif // MAINWINDOW_H
#ifndef WEBVIEW_H
#define WEBVIEW_H
#include <QWebView>
class MainWindow;
class WebView : public QWebView
{
public:
WebView(MainWindow *interface, QWidget *parent = 0);
private:
MainWindow *interface;
};
#endif // WEBVIEW_H
#include "webview.h"
WebView::WebView(MainWindow *interface, QWidget *parent) : QWebView(parent), interface(interface)
{
QObject::connect(this, SIGNAL(titleChanged(QString)), this->interface, SLOT(setTabTitle(QString)));
QObject::connect(this, SIGNAL(urlChanged(QUrl)), this->interface, SLOT(adressChanged(QUrl)));
QObject::connect(this, SIGNAL(loadProgress(int)), this->interface, SLOT(setProgressionValue(int)));
}
When you call QObject::connect() method class MainWindow must be fully qualified. In your case you just forward declare it, so compiler has no idea, that MainWindow is inherited from QMainWindow. Just add #include "mainwindow.h" into webview.cpp
Related
I have one MainWindow and one Class; I want to send data between them using custom signal and slot. I can't seem to figure it out, I need help.
Here is my code:
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <iostream>
#include "receive.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
signals:
void sendit(QString name);
private slots:
void on_send_button_clicked();
void display(QString e)
{
std::cout<<"Here is where I am called this "<<e.toStdString()<<std::endl;
}
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "receive.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
Receive *r = new Receive();
connect(this, SIGNAL(sendit(QString)), r, SLOT(display(QString)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_send_button_clicked()
{
emit sendit(ui->lineEdit->text());
}
receive.h
#ifndef RECEIVE_H
#define RECEIVE_H
#include <iostream>
#include <QDialog>
class Receive : public QDialog
{
public:
Receive();
private slots:
void display(QString e);
};
#endif // RECEIVE_H
receive.cpp
#include "receive.h"
#include "mainwindow.h"
Receive::Receive()
{
}
void Receive::display(QString e)
{
std::cout<<"Here is where I am called this "<<e.toStdString()<<std::endl;
}
When I run this program, I get this message:
06:26:29: Starting C:\Users\Troy\Documents\build-tests-Desktop_Qt_5_14_1_MinGW_32_bit-Debug\tests.exe ...
QObject::connect: No such slot QDialog::display(QString) in ..\tests\mainwindow.cpp:11
QObject::connect: (sender name: 'MainWindow')
How do I get this done, please?
Thank you for your help.
Your slot in Receive needs to be public not private. Much the same as other class members, private slots can only be used by the class itself.
If you use the modern connect syntax you'll get a better compile time error:
connect(this, &MainWindow::sendit, r, &Receive::display);
You also need to make sure you add Q_OBJECT to every Qt class, it is missing from Receive.
I want to separate my roles in a game to different .cpp and .h files,
but I have trouble calling the pointer in mainwindow from another class, which I added through scene->add() in mainwindow.cpp.
It shows "player" was not declared in this scope when I run.
I know this question seems pretty basic, but I've tried my best to fix it with no results.
The following are main methods I've tried:
add MainWindow:: before player, but it shows the similar error
that mainwindow is not declared in this scope.
revise player to this pointer, and it says that class Player has no such member.
revise player to pos() pointer, it says pos() is not
declared in this scope
set class Player as friend with main window, but nothing changes
Here is the code:
main window.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
scene(new QGraphicsScene(0,0,800,600)),
timer(new QTimer)
{
ui->setupUi(this);
ui->graphicsView->setScene(scene);
player = new QGraphicsPixmapItem(QPixmap(":/img/whitedog.png").scaled(150,150));
scene->addItem(player);
player->setPos(0, 0);
timer->start(10);
}
MainWindow::~MainWindow()
{
delete ui;
}
main window.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QTimer>
#include <QKeyEvent>
#include "player.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
friend class Player;
~MainWindow();
private:
Ui::MainWindow *ui;
QGraphicsScene *scene;
QTimer *timer;
QGraphicsItem *player;
};
#endif // MAINWINDOW_H
player.cpp
#include "player.h"
Player::Player()
{
}
void Player::keyPressEvent(QKeyEvent *e)
{
switch(e->key()) {
case Qt::Key_Up:
player->setPos(player->x(), player->y()-10);
break;
}
}
player.h
#ifndef PLAYER_H
#define PLAYER_H
#include <QKeyEvent>
#include <QGraphicsScene>
#include <QMainWindow>
#include <QGraphicsPixmapItem>
#include <QTimer>
#include "ui_mainwindow.h"
class Player
{
public:
Player();
void keyPressEvent(QKeyEvent *e);
};
#endif // PLAYER_H
You are getting confused between two different things.
You have a class Player, which I believe is the one that you want to declare in mainwindow.h but an object of class Player is not created anywhere( as far as what is shown above ).
The player currently declared in the mainwindow.h is of type QGraphicsItem and not of the Player class that you created, so you cannot expect your keyPressEvent to work on it.
You need to have a second look at your design, know the purpose of the Player class, it's responsibilities. Currently it is a simple class not inheriting from anything, did you want it to maybe inherit from QGraphicsItem.
In such a case, your class maybe could look something like this :
class Player : public QGraphicsItem
{
//Players's responsibilities.
}
And in your mainwindow.h, you can just use the instance of the Player instead of using a QGraphicsItem instance.
class MainWindow : public QMainWindow
{
...// other stuff
private:
Player *player;
}
Additional Pointers :
1 . I don't see a reason for the Player class to be a friend class in mainwindow.h, but then again it is your design.
2 . Prefer initializing the player object part in the member initialization list rather than doing it in the constructor.
i'm trying to change the label text of Class A via Class B using Qt but i can't get it working, here's my codes:
Class A:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "loldata.h"
using namespace std;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
LoLData *lold = new LoLData();
QObject::connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(updateData()));
QObject::connect(lold, SIGNAL(updatePlayerID(QString)), ui->label, SLOT(setText(QString)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::updateData()
{
LoLData summoner;
summoner.getSummonerData("Snylerr");
}
Class A: (.h)
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QObject>
#include <string>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void updateData();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Class B:
#include "loldata.h"
#include "mainwindow.h"
using namespace std;
int LoLData::getSummonerData(QString playerName)
{
emit updatePlayerID("playerName");
return 0;
}
Class B: (.h)
#ifndef DEF_LOLDATA
#define DEF_LOLDATA
#include <QApplication>
#include <QObject>
#include <string>
class LoLData : public QObject
{
Q_OBJECT
public:
int getSummonerData(QString playerName);
signals:
void updatePlayerID(QString playerName);
private:
};
#endif
You can see that i tried to use slots and signals but the text of the label is not changing, i saw a lot of examples on internet but i can't get them working
Thanks for your reply.
You are creating a new instance of LoLData here:
void MainWindow::updateData()
{
LoLData summoner;
summoner.getSummonerData("Snylerr");
}
This instance of LoLData named summoner is not connected to your label's setText slot.
LoLData *lold = new LoLData(); - this instance of LolData is connected to you label's setText slot.
What should yo do?
It depends on what you want to accomplish:
either connect your summoner instance to the label by inserting a QObject::connect(&summoner...) inside yourupdateData` method;
or you don't instantiate a new LolData variable and use lold inside your updateData function:
void MainWindow::updateData()
{
lold->getSummonerData("Snylerr");
}
Also in this case you have to put lold as a member variable.
In your MainWindow constructor, you connect your lold object to the setText slot.
But in updateData, you use an other object (summoner) which is not connect to anything. So when you use getSummonerData on summoner, the signal updatePlayerID is emitted nut they is no slot connected to it.
I'm using Qt 5.7 trying to use a timer with timeout event in a class named MyClass. I created a public variable of this class in mainwindow.h. I put the timer's slot connect in the constructor of MyClass, and have a function in MyClass to start the timer. But when I execute the function, the timer slot doesn't work.
I have no error in building, but I get the comment below on the application window at run time:
QObject::connect: No such slot QObject::on_timeout()
Here is my code:
The mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "myclass.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MyClass mc;
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
The mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "myclass.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
mc.TimerStart();
}
myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QTimer>
class MyClass : public QObject
{
public:
MyClass();
TimerStart();
QTimer *timer;
public slots:
on_timeout();
};
#endif // MYCLASS_H
myclass.cpp
#include "myclass.h"
#include <QMessageBox>
#include <QTimer>
MyClass::MyClass()
{
timer = new QTimer(this);
}
MyClass::TimerStart()
{
timer->setInterval(1000);
connect(timer, SIGNAL(timeout()), this, SLOT(on_timeout()));
timer->start(1000);
}
MyClass::on_timeout()
{
QMessageBox msg;
msg.setText("updated");
msg.exec();
}
You forgot to add the Q_OBJECT to MyClass,
You're reentering the event loop in on_timeout.
You're setting the timer's interval multiple times.
You're connecting to the timer's signal multiple times.
You're making an implementation detail (the on_timeout slot) public.
You're pessimizing your code by manually managing the memory for QTimer.
You're including <QTimer> twice.
It's 2016 and you're not using C++11. Yes, you can use it even with Qt 4.
Here's how I'd write it:
Qt 5
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QTimer>
#include <QMessageBox>
class MyClass : public QObject
{
Q_OBJECT
QMessageBox msg;
QTimer timer{this};
public:
explicit MyClass(QObject * parent = nullptr);
void timerStart();
};
#endif // MYCLASS_H
#include "myclass.h"
MyClass::MyClass(QObject * parent) : QObject{parent}
{
msg.setText(QStringLiteral("updated"));
connect(&timer, &QTimer::timeout, &msg, &QMessageBox::show);
}
void MyClass::timerStart()
{
timer.start(1000);
}
Qt 4
Here I demonstrate that implementation details should be private. You could of course do as above and set the msg's text in the constructor, and connect directly to the msg's SLOT(show()).
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QTimer>
#include <QMessageBox>
class MyClass : public QObject
{
Q_OBJECT
QMessageBox msg;
QTimer timer{this};
Q_SLOT void on_timeout();
public:
explicit MyClass(QObject * parent = nullptr);
void timerStart();
};
#endif // MYCLASS_H
#include "myclass.h"
MyClass::MyClass(QObject * parent) : QObject{parent}
{
connect(&timer, SIGNAL(timeout()), SLOT(on_timeout()));
}
void MyClass::timerStart()
{
timer.start(1000);
}
void MyClass::on_timeout()
{
msg.setText("updated");
msg.show();
}
You forgot to add Q_OBJECT in your class declaration:
class MyClass : public QObject
{
Q_OBJECT
// ...
If you're using Qt 5.7, you should use the Qt5 syntax for connect:
connect(timer, &QTimer::timeout, this, &MyClass::on_timeout);
By doing so, the connection will be evaluated at compile time instead of runtime. Moreover, you can connect a signal to functions even if they are not declared as slots (so you won't need the Q_OBJECT identifier in the class declaration).
More info here.
I am new to qt and I am trying to create a program where the MainWindow calls a QDialog to enter some data.
The problem is that the parent() at my QDialog does not have any access to the public methods of the MainWindow in our case the
void save_city(const City *city); //public method of MainWindow
The code is actually big so here is some of the code.Thanks.
mainwindow.h
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QMainWindow>
#include <QTextStream>
#include <QVector>
#include <QDebug>
#include <QFile>
#include "dialog_add_city.h"
#include "street.h"
#include "city.h"
#include "map.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
//main Window constructor
explicit MainWindow(QWidget *parent = 0);
//main Window deconstructor
~MainWindow();
/*utility function to save the city
*the function is public so that also QDialogs
*data saves can */
//////////////
//here is the public function
void save_city(const City *city);
private slots:
private:
Map mainMap;
Ui::MainWindow *ui;
QGraphicsView view;
QGraphicsScene scene;
};
dialog_add_city.h
#ifndef DIALOG_ADD_CITY_H
#define DIALOG_ADD_CITY_H
#include <QDialog>
#include "mainwindow.h"
#include "City.h"
namespace Ui {
class Dialog_Add_City;
}
class Dialog_Add_City : public QDialog
{
Q_OBJECT
public:
explicit Dialog_Add_City(QWidget *parent = 0);
~Dialog_Add_City();
private slots:
//Add New City Button clicked-Adds an new city to our city_locations.txt
void on_PushButton_Add_New_City_clicked();
private:
Ui::Dialog_Add_City *ui;
};
#endif // DIALOG_ADD_CITY_H
dialog_add_city.cpp
#include "dialog_add_city.h"
#include "ui_dialog_add_city.h"
Dialog_Add_City::Dialog_Add_City(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog_Add_City)
{
ui->setupUi(this);
}
Dialog_Add_City::~Dialog_Add_City()
{
delete ui;
}
void Dialog_Add_City::on_PushButton_Add_New_City_clicked()
{
City *city=new City(ui->lineEdit_cityName->text(),
ui->lineEdit_X_Ko->text().toDouble(),
ui->lineEdit_Y_Ko->text().toDouble());
qDebug() << ui->lineEdit_cityName->text()
<< ui->lineEdit_X_Ko->text()
<< ui->lineEdit_Y_Ko->text();
/////////////////////////////
//HERE IS THE PROBLEM
parent()->save_city(city);
}
Any other suggestions are welcomed!
The Problem is that parent() will return a pointer the parent object as QObject.
QObject Documentation
As dreschrjm pointed out you could try to cast the object via
MyWidget *myWidget = qobject_cast<MyWidget *>(obj);
from The Meta-Object System
Suggestion: Use Qt's signal/slot mechanism to avoid a backward reference to the parent.
Declare save_city as signal in Dialog_Add_City.
Declare save_city in MainWindow as slot
Connect both where the dialog is created:
e.g.
void MainWindow::show_add_city_dialog()
{
Dialog_Add_city dialog;
connect(&dialog, &Dialog_Add_city::save_city, this, &MainWindow::save_city);
dialog.exec();
}
Replace parent()->save_city(city); in Dialog_Add_City with emit save_city(city);
Ensure that the new city object doesn't leak, I think a better design would be to create the City object elsewhere not in the dialog.
so
emit save_city(ui->lineEdit_cityName->text(),
ui->lineEdit_X_Ko->text().toDouble(),
ui->lineEdit_Y_Ko->text().toDouble());
and the slot
void MainWindow::save_city(const QString &cityName, double x, double y)
{
City *city=new City(cityName, x, y);
// do some interresting things with city.
}