Signals and slots not working in qt - c++

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

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

Database not opening error qt c++

I have created a class named MainWIndow which has a method(getconnOpen) to provide database connection! following is my code!
MainWindow.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
QSqlDatabase mydb;
bool getconnOpen(QString uname,QString pword,QString ip,int port,QString dbname){
mydb=QSqlDatabase::addDatabase("QOCI");
mydb.setUserName(uname);
mydb.setPassword(pword);
mydb.setHostName(ip);
mydb.setPort(port);
mydb.setDatabaseName(dbname);
mydb.open
return true;
}
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
MainWindow.cpp
void MainWindow::on_pushButton_clicked()
{
Dialog *dialog1=new Dialog(this);
if(getconnOpen(ui->lineEdit->text(),ui->lineEdit_2->text(),ui->lineEdit_3->text(),ui->lineEdit_4->text().toInt(),ui->lineEdit_5->text()){
dialog1->show();
}
}
Dialog.h
class Dialog : public QDialog
{
Q_OBJECT
public:QSqlDatabase mydb;
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private slots:
void on_pushButton_clicked();
Dialog.cpp
void Dialog::on_pushButton_clicked()
{
QSqlQueryModel modal = new QSqlQueryModel();
QSqlQuery qry=new QSqlQuery(mydb);
qry->prepare("select User FROM USERS");
qry->exec();
modal->setQuery(*qry);
ui->tableView->setModel(modal);
}
Though I opened the connection in MainWindow.h the query in dialog.cpp gives an error stating "database not open" ! But I opened the databse in MainWindow.cpp! How can I correct this?
Try something like this (mind you I do not have time to test this so you may need to tweak it) And I am annoyed that it created a cyclical dependence between the MainWindow and Dialog.. you can undo that by creating a dbmanager class or using a shared pointer to the mydb instead. but this is the quickest thing I could type for you without having to redesign all your code.
MainWindow.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
QSqlDatabase mydb;
bool getconnOpen(QString uname,QString pword,QString ip,int port,QString dbname){
mydb=QSqlDatabase::addDatabase("QOCI");
mydb.setUserName(uname);
mydb.setPassword(pword);
mydb.setHostName(ip);
mydb.setPort(port);
mydb.setDatabaseName(dbname);
// Return the actual state of the db instead of return true.
return mydb.open();
}
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
MainWindow.cpp
void MainWindow::on_pushButton_clicked()
{
Dialog *dialog1=new Dialog(this);
if(getconnOpen(ui->lineEdit->text(),ui->lineEdit_2->text(),ui->lineEdit_3->text(),ui->lineEdit_4->text().toInt(),ui->lineEdit_5->text()){
dialog1->show();
}
}
Dialog.h
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private slots:
void on_pushButton_clicked();
Dialog.cpp
void Dialog::on_pushButton_clicked()
{
QSqlQueryModel modal = new QSqlQueryModel();
// get the db object from the parent widget, if the parent widget returned is not of the MainWindow type then dynamic_cast will return NULL.
MainWindow *mainWindow = dynamic_cast<MainWindow(parentWidget());
// if all went well then mainWindow is not NULL but should test first.
if (mydb != NULL)
{
QSqlQuery qry=new QSqlQuery(mainWindow->mydb);
qry->prepare("select User FROM USERS");
qry->exec();
modal->setQuery(*qry);
ui->tableView->setModel(modal);
}
// do something else if the pointer is NULL.
}
I am not happy with doing it this way:
*********** OK FOUND THE RIGHT WAY TO DO IT I THINK!*********************
from this post Handling QSqlDatabase connections
looks like QSqlDatabase is already a connection manager so you add the connection once and retrieve it by name from your other form. Again I do not have the ability to test this but this would be a better approach as it uses the QT connection manager as it is intended and there are no cyclical dependencies between MainWindow and the Dialog.
MainWindow.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
QSqlDatabase mydb;
bool getconnOpen(QString uname,QString pword,QString ip,int port,QString dbname){
// Add the database by name so you can retrieve it later. I would also
// not hardcode the name like this but this.. yuck but hey you can fix
// that yourself ;)
mydb=QSqlDatabase::addDatabase("QOCI", "MyDbConnection");
mydb.setUserName(uname);
mydb.setPassword(pword);
mydb.setHostName(ip);
mydb.setPort(port);
mydb.setDatabaseName(dbname);
// Return the actual state of the db instead of return true.
return mydb.open();
}
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
MainWindow.cpp
void MainWindow::on_pushButton_clicked()
{
Dialog *dialog1=new Dialog(this);
if(getconnOpen(ui->lineEdit->text(),ui->lineEdit_2->text(),ui->lineEdit_3->text(),ui->lineEdit_4->text().toInt(),ui->lineEdit_5->text()){
dialog1->show();
}
}
Dialog.h
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private slots:
void on_pushButton_clicked();
Dialog.cpp
void Dialog::on_pushButton_clicked()
{
QSqlQueryModel modal = new QSqlQueryModel();
// make sure the database exists.
if (QSqlDatabase::contains("MyDbConnection");)
{
// retrieve the database by name from the database manager.
QSqlQuery qry=new QSqlQuery(QSqlDatabase::database("MyDbConnection"));
qry->prepare("select User FROM USERS");
qry->exec();
modal->setQuery(*qry);
ui->tableView->setModel(modal);
}
// do something else if the pointer is NULL.
}

findChild never displays textBrowser

I trying to display some text to a textbrowser via: FindChild and it never displays it in the textbrowswer any help would be helpfull..
Here is my mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
namespace Ui
{
class MainWindow;
class TestWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
static MainWindow* GetInstance(QWidget* parent = 0);
signals:
public slots:
void on_pushButton_3_clicked();
void MainWindow_TextBrowser_String(const QString & newText);
private:
Ui::MainWindow *ui;
static MainWindow* mainInstance;
};
Here is my mainwindow.cpp
// Constructor
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
// Destructor
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_3_clicked()
{
TestWindow mwindow;
mwindow.start();
}
MainWindow* MainWindow::mainInstance = 0;
MainWindow* MainWindow::GetInstance(QWidget *parent)
{
if (mainInstance == NULL)
{
mainInstance = new MainWindow(parent);
}
return mainInstance;
}
void MainWindow::MainWindow_TextBrowser_String(const QString & newText)
{
QString TextBrowser_String = QString(newText);
ui->textBrowser->append(TextBrowser_String);
}
I create the testwindow object in the pushbutton send the start function to call the findchild window to send a string to the textbrowser window
Here is my testwindow.cpp
void testwindow::start()
{
// Create a new mainwindow on the heap.
MainWindow* instance = MainWindow::GetInstance();
// Or I can call
// MainWindow instance; then point to findchild
QString Test_Window_String = QStringLiteral("Test Window String");
instance->findChild<QTextBrowser*>("textBrowser")->append(Test_Window_String);
}
I understand that you can use a singal and slot and simply just create a signal that sends the string to the append textbrowser
void testwindow::singalandslot()
{
MainWindow* instance = MainWindow::GetInstance();
connect(this, SIGNAL(TextBrowswer_String(const QString &)), instance , SLOT(MainWindow_TextBrowser_String(QString &)));
}
void testwindow::fireSignal()
{
emit TextBrowswer_String("sender is sending to receiver.");
}
Even with a signal or FindChild it seems that the object is already deleted or i'm doing something wrong.
Can you please share your Ui::MainWindow Class and setupUi implementation to get a clear view?
Hope you have created the instance for QTextBrowser* inside setupUi or in the constructor.
With the below setupUi implementation, both ur usecases are working.
namespace Ui
{
class MainWindow: public QWidget
{
Q_OBJECT
public:
QTextBrowser* textBrowser;
void setupUi(QWidget* parent)
{
setParent(parent);
textBrowser = new QTextBrowser(parent);
textBrowser->setObjectName("textBrowser");
textBrowser->setText("Hello");
}
};
}

Using the autogenerated Ui for both sender and receiver with qt

I need to call a method after the ui has been shown,so i want to connect
the frame with itself,in particular using the show signal.
I've created a new form with auto generated code by qtcreator.This is the auto generated header.
#define STARTWINDOW_H
#include <QMainWindow>
namespace Ui {
class StartWindow;
}
class StartWindow : public QMainWindow
{
Q_OBJECT
public:
explicit StartWindow(QWidget *parent = 0);
~StartWindow();
private:
Ui::StartWindow *ui;
public slots:
void doSomething();
};
#endif // STARTWINDOW_H
in the cpp file no one of the following codes work
connect(ui,SIGNAL(QEvent::Show),this,SLOT(doSomething()));
connect(*ui,SIGNAL(QEvent::Show),this,SLOT(doSomething()));
connect(this->ui,SIGNAL(QEvent::Show),this,SLOT(doSomething()));
What's the right way to do it?
That signal does not exist by default, we must create it, we can override the showEvent() method:
.h
protected:
void showEvent(QShowEvent *event);
signals:
void showSignal();
.cpp
connect(this, &StartWindow::showSignal, this, &StartWindow::doSomething);
void StartWindow::showEvent(QShowEvent *event)
{
emit showSignal();
QMainWindow::showEvent(event);
}
void StartWindow::doSomething()
{
qDebug()<<"show";
}
Or you can override the eventFilter method.
.h
protected:
bool eventFilter(QObject *watched, QEvent *event);
signals:
void showSignal();
.cpp
installEventFilter(this);
connect(this, &StartWindow::showSignal, this, &StartWindow::doSomething);
bool StartWindow::eventFilter(QObject *watched, QEvent *event)
{
if(watched==this && event->type() == QEvent::Show)
emit showSignal();
return QMainWindow::eventFilter(watched, event);
}
There are a few things wrong here:
There is no show() signal and
Even if there were, you aren't using connect correctly.
First, if your class were defined like this:
namespace Ui { class MainWindow; }
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void someSignal();
public slots:
void doSomething() {}
private:
Ui::MainWindow *ui;
};
The appropriate call to connect in the constructor would be:
QWidget::connect(this, SIGNAL(someSignal()), this, SLOT(doSomething()));
Even if there were a show signal, you wouldn't get it from ui, you would get it from this. The UI classes are just dumb containers for widgets that you add through the designer.
To perform some action when your class is shown, you can either override
virtual void showEvent(QShowEvent *); (more robust, but slightly more complex)
or simply define your own show() slot that does what you want and calls QWidget::show() at the end of it. I prefer the latter, so I will show you that.
Start by defining your show slot like this:
namespace Ui { class MainWindow; }
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void doSomething() {}
void show();
private:
Ui::MainWindow *ui;
};
Then, in your implementation file, do this:
void MainWindow::show()
{
doSomething();
QWidget::show();
}
I have worked with the Qt framework for quite some time now, and I have never needed to override the show event; it is simply not worth it for most use cases. If you really want a show signal that others can connect to, just add a custom signal for it and emit in in MainWindow::show(). Only resort to overriding event handlers if you can't make this work for what you are doing(very rarely necessary).

Qt: Connect Signals and Slots Across Differnet Files

I am a newbie in Qt and C++ programming. I have some problem in my program that i need a solution for.
I have two files MainWindow.h and ChatWindow.h, which contains two classes of MainWindow and ChatWindow.
This is chatwindow.h
namespace Ui {
class ChatWindow;
}
class ChatWindow : public QMainWindow
{
Q_OBJECT
public:
explicit ChatWindow(QWidget *parent=0);
~ChatWindow();
private slots:
void send_chat_fn(pjsua_call_id call_id);
void rcv_chat_fn(pjsua_call_id call_id);
void rcv_msg_fn(QString msg);
void on_pushButton_clicked();
void on_actionQuit_triggered();
private:
Ui::ChatWindow *ui;
};
And this is mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void add_item(QString buddy_uri);
signals:
void send_chat(pjsua_call_id call_id);
void rcv_chat(pjsua_call_id call_id);
void rcv_msg(QString msg);
private slots:
void on_actionAdd_Buddy_triggered();
void on_actionQuit_triggered();
void on_actionStatus_triggered();
void on_actionNew_Chat_triggered();
void on_action_Configuration_triggered();
void on_listWidget_doubleClicked(const QModelIndex &index);
private:
Ui::MainWindow *ui;
};
Now i want to connect signals from mainwindow.h to slots in chatwindow.h.
I have tried connection in the constructor of class ChatWindow, but it does not work (i think that is because connections work on instances not on classes). Instance of MainWindow class which i want to connect is in mainwindow.cpp. Defining instances of class ChatWindow in MainWindow gives error:
Cannot set parent, parent is in different thread
And if i create a new instance in Constructor of ChatWindow, then it doesnt connect to the desired instance.
Its a complete mess. Please help me through this.