Qt C++ How to connect a class's instance from other class - c++

I have three C++ classes: DB, MainWindow and Login. The instance of DB resides as database in MainWindow, and a button calls the instance of Login called loginDialog. Now I want to connect loginDialog's accept() with database's (DB's) slot, but since the instance database resides in MainWindow, I'm confused as to how to access it.
DB.h
public:
void login(QString name,QString id,QString pass);
DB.cpp
void DB::login(QString name, QString id,QString pass){
qInfo()<<"Login approved"; //placeholder
}
MainWindow.h
private:
DB database;
public slots:
void dblogin(QString name,QString id,QString pass);
private slots:
void showLoginPage();
MainWindow.cpp
#include "Login.h"
MainWindow::MainWindow(QWidget *parent):QDialog(parent),ui(new Ui::MainWindow){
ui->setupUi(this);
connect(ui->pushButton,&QPushButton::clicked,this,&MainWindow::showLoginPage);
}
void MainWindow::dblogin(QString name, QString id, QString pass){
database.login(name,id,pass);
}
void MainWindow::showLoginPage(){
Login loginDialog;
loginDialog.exec();
}
Login.h
signals:
void makeLogin(QString name,QString id,QString pass);
private slots:
void startLogin();
Login.cpp
Login::Login(QWidget *parent):QDialog(parent),ui(new Ui::Login){
ui->setupUi(this);
connect(this,&QDialog::accept,this,&Login::startLogin);
connect(this,&Login::makeLogin,&MainWindow,&MainWindow::dblogin); //Error
}
void Login::startLogin(){
emit makeLogin(ui->f1->text(),ui->f2->text(),ui->f3->text());
}

As mentioned in the comments, make MainWindow the parent of Login and make the connection.
I suggest also that your IOController should be a member of MainWindow so that everything would be centered.
If things get complicated with connections, you can access to public members of MainWindow like that :
auto theParent = qobject_cast<MainWindow*>(this->parent());
if(theParent)
{
// access to any member of MainWindow
}

Related

connecting a checkbox signal to a method in qt widget

For example I have a three files
the generalsetting.ui, generalsetting.h, generalsetting.cpp .
I want to trigger the enableNotification method when the Notifycheckbox in the UI file is clicked.
by passing the return value of the checkbox to the function
I tried using
connect(ui->notifyCheckBox, &QCheckBox::toggled, this, enableNotification(&QCheckBox::toggled));
and
connect(ui->notifyCheckBox, &QCheckBox::isChecked, this, enableNotification(&QCheckBox::toggled));
it does not work
here is the both the header and source
namespace Ui {
class GeneralSettings;
}
class GeneralSettings : public QWidget
{
Q_OBJECT
public:
explicit GeneralSettings(QWidget *parent = nullptr);
~GeneralSettings() override;
private slots:
void enableNotification(bool enable);
private:
Ui::GeneralSettings *ui;
Utils *utils;
};
the source File
GeneralSettings::GeneralSettings(QWidget *parent) :
QWidget(parent),
ui(new Ui::GeneralSettings)
{
ui->setupUi(this);
//here is where i am adding the connect function.
}
void GeneralSettings::enableNotification(bool enable)
{
utils->settings->setValue("General/notify", enable);
}
PS:i included only the ones that i feel are useful
you can connect to a lambda:
connect(ui->yyy, &QCheckBox::toggled, [this]()
{
qDebug() << "sd.." << ui->yyy->isChecked();
enableNotification(ui->yyy->isChecked());
});
or directly, same way as the signal
connect(ui->yyy, &QCheckBox::toggled,this, &Foo::enableNotification);

Is it normal not to be able to reuse a variable obtained from a connect()?

I made a login page and I'm trying to retrieve the name of the user who logged in and then display it in the next page and to adjust my program according to the person logged in.
But I desperately run into the same problem, I can't extract the variable from the slot to reuse it and do everything I have to do with it :(
So I wonder if it's a specificity of the slot (I start Qt and I don't know much about it) or if I'm the one who doesn't do things correctly.
PS: I've obviously read and reread the Qt documentation about this but it doesn't help too much.
My code:
glybook.cpp (where I want to put the login information)
#include "ui_glybook.h"
glybook::glybook(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::glybook)
{
ui->setupUi(this);
//qDebug() << receiveConnectionData(username);
test();
}
void glybook::receiveConnectionData(QString name){
username = name;
//qDebug() << username;
ui->label->setText("Connected: "+username);
}
void glybook::test(){
qDebug() << ui->label->text();
}
glybook::~glybook()
{
delete ui;
}
glybook.h
class Glybook;
}
class Glybook : public QMainWindow
{
Q_OBJECT
public:
explicit Glybook(QWidget *parent = nullptr);
~Glybook();
void test();
private slots:
void receiveConnectionData(QString);
private:
Ui::Glybook *ui;
QString username;
};
connection.cpp (login page)
#include "./ui_connection.h"
Connection::Connection(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::Connection)
{
ui->setupUi(this);
}
Connection::~Connection()
{
delete ui;
}
void Connection::on_pushButton_clicked()
{
QString user = ui->lineEdit->text();
QString pass = ui->lineEdit_2->text();
glybook* page = new glybook();
connect(this, SIGNAL(sendConnectData(QString)), page, SLOT(receiveConnectionData(QString)));
emit sendConnectData(user);
page->show();
this->close();
}
connection.h
#define CONNECTION_H
#include <QMainWindow>
#include <QMessageBox>
#include "glybook.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Connection; }
QT_END_NAMESPACE
class Connection : public QMainWindow
{
Q_OBJECT
public:
Connection(QWidget *parent = nullptr);
~Connection();
private slots:
void on_pushButton_clicked();
signals:
void sendConnectData(QString);
private:
Ui::Connection *ui;
};
#endif // CONNECTION_H
main.cpp
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Connection w;
w.show();
return a.exec();
}
Cause
You call the test method of glybook in its constructor, which is executed as a result of this line:
glybook* page = new glybook();
At that time neither the connection
connect(this, SIGNAL(sendConnectData(QString)), page, SLOT(receiveConnectionData(QString)));
is made, nor the signal sendConnectData is emitted, so your qDebug() << ui->label->text(); prints an empty QString.
Solution
If you want to see the value sent by Connection in glybook, check it AFTER the execution of the receiveConnectionData slot.
That being said, I highly suggest you to read about Object Oriented Programming, as well as to go through a well known Qt course by VoidRealms on Youtube.

Signals and slots not working in qt

in my Qt program I need the dialog to send a signal to a slot in the mainwindow. I have set the connection up correctly to the best of my knowledge and it does not give me any errors during compile or run time but for some reason it just doesn't do anything when the button that is supposed to activate the signal is clicked. Why is this happening?
beastiary.h (mainwindow header)
namespace Ui {
class Beastiary;
}
class Beastiary : public QMainWindow
{
Q_OBJECT
public:
explicit Beastiary(QWidget *parent = 0);
Ui::Beastiary *ui;
QStringList MyList;
~Beastiary();
public slots:
void refresh();
private slots:
void on_pushButton_clicked();
void on_listWidget_itemClicked(QListWidgetItem);
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
beastiary.cpp (mainwindow cpp file)
Beastiary::Beastiary(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Beastiary)
{
ui->setupUi(this);
Dialog dialog;
connect(&dialog, SIGNAL(gorefresh()),this, SLOT(refresh())) ;
void Beastiary::refresh()
{
qDebug () << "recieved";
ui->listWidget->clear();
QString path = "C:/Program Files/Bargest/bin";
QDir myPath(path);
myPath.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
MyList = myPath.entryList();
ui->listWidget->addItems(MyList);
}
dialog.h
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
signals:
void gorefresh();
private slots:
void on_pushButton_done_clicked();
void on_pushButton_cancel_clicked();
void on_pushButton_clicked();
private:
Ui::Dialog *ui;
dialog.cpp
void Dialog::on_pushButton_done_clicked()
{
emit gorefresh();
}
I did leave out large parts of the code that just have nothing to do with the actual signals and slots mechanism at play here.
You're only connecting the dialog instance you created locally in the Bestiary's constructor, which goes out of scope as the constructor finishes.
connect is connecting instances, not classes. That means you need to connect each created dialog:
void Beastiary::on_pushButton_clicked() {
Dialog* ad = new Dialog(this);
connect(ad, SIGNAL(gorefresh()), this, SLOT(refresh()));
ad->show();
}
While at it, you should seriously consider using the type-safe connect syntax that came with Qt 5:
void Beastiary::on_pushButton_clicked() {
Dialog* ad = new Dialog(this);
connect(ad, &Dialog::gorefresh, this, &Bestiary::refresh));
ad->show();
}

Disconnecting signals fails

In my code I want to reroute a signal-slot-connection, i.e. first the slot is connected to signal 1, and after the rerouting it should only be connected to signal 2. For that I used disconnect(this), with this referring to the class which owns the slots (it is in a class function). This command should disconnect all signals from extern from the class. Unfortunately, I get false as return value of disconnect(). Why can't I disconnect the signals? Is there a possibility to get more information?
Strangely, in my example below the disconnect and reconnect does not work, too, I get the same error code from disconnect.
If I remove the line connect(this, &MainWindow::writeLine, class1, &TXClass::emit_signal); from the on_PushButton2_clicked()-function, disconnect() still returns "false", but I get the expected result.
Example code:
Mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
class1 = new TXClass("Class 1");
class2 = new TXClass("Class 2");
connect(this, SIGNAL(writeLine()), class1, SLOT(emit_signal()));
connect(class1, SIGNAL(signal(QString)), this, SLOT(newText(QString)));
}
MainWindow::~MainWindow()
{
delete class1;
delete class2;
delete ui;
}
void MainWindow::newText(QString text)
{
ui->lineEdit->setText(text);
}
void MainWindow::on_pushButton_clicked()
{
emit writeLine();
}
void MainWindow::on_pushButton_2_clicked()
{
qDebug() << "Disconnect result: " << disconnect(this);
connect(this, &MainWindow::writeLine, class2, &TXClass::emit_signal);
connect(this, &MainWindow::writeLine, class1, &TXClass::emit_signal);
connect(class2, &TXClass::signal, this, &MainWindow::newText);
//The onliest signal I want to get now is from class2.
}
MainWindow.h:
#include <QDebug>
#include <txclass.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void writeLine(void);
public slots:
void on_pushButton_clicked();
void newText(QString text);
void on_pushButton_2_clicked();
private:
Ui::MainWindow *ui;
TXClass *class1, *class2;
};
#endif // MAINWINDOW_H
TXClass.cpp:
#include "txclass.h"
TXClass::TXClass(QString name)
{
TXClass::name = name;
}
void TXClass::emit_signal()
{
emit signal(name);
}
TXClass.h:
#ifndef TXCLASS_H
#define TXCLASS_H
#include <QObject>
class TXClass : public QObject
{
Q_OBJECT
private:
QString name;
signals:
void signal(QString string);
public slots:
void emit_signal(void);
public:
TXClass(QString name);
};
#endif // TXCLASS_H
I've checked how QObject::disconnect is implemented and I don't see how this is supposed to work if you only specify receiver. QMetaObjectPrivate::disconnect will return immediately with false when sender is not specified. This means that second part of QObject::disconnect will no set res to true. The only other place you could get true out of is call to QInternal::activateCallbacks. But it doesn't look like it's instance specific, rather some global stuff (I admit I have no idea what exactly is this suppose to do :/).
I solution that works and seems good enough is this:
void MainWindow::second()
{
qDebug() << "Disconnect result: " << class1->disconnect();
connect(this, &MainWindow::writeLine, class2, &TXClass::emit_signal);
connect(this, &MainWindow::writeLine, class1, &TXClass::emit_signal);
connect(class2, &TXClass::signal, this, &MainWindow::newText);
//The onliest signal I want to get now is from class2.
}

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()));