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);
Related
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();
}
I've tried to emit a custom signal login() from my loginmanager class to the mainwindow. The signal is fired on the loginButtonClicked slot, and to my understand on the signal/slot mechanism, it should be able to capture any signal fired event and "look" for the corresponding slot to be execute. But it doesn't work as what I've think.
The connect function returns 1, which means it is able to be implemented in the moc file, and it DOES work if i run the m_LoginManager->setLogin() which fires the login() signal.
But what I prefer is the signal is emitted by the loginButton, and pass to the mainwindow to be process (in this case, init()).
Please correct me if I'm wrong.
Below are the code.
loginmanager.cpp
LoginManager::LoginManager(QWidget * parent) : QWidget(parent)
{
ui.setupUi(this);
connect(ui.loginButton, SIGNAL(clicked()), this, SLOT(loginButtonClicked());
}
LoginManager::~LoginManager()
{
}
void LoginManager::setLogin()
{
emit login();
}
void LoginManager::loginButtonClicked()
{
setLogin();
}
loginmanager.hpp
#include <QWidget>
#include "ui_loginmanager.h"
class DatabaseManager;
class SettingManager;
class LoginManager : public QWidget
{
Q_OBJECT
public:
LoginManager(QWidget * parent = Q_NULLPTR);
~LoginManager();
void setLogin();
signals:
void login();
public slots:
void loginButtonClicked();
private:
Ui::LoginManager ui;
};
mainwindow.hpp
#include <QtWidgets/QMainWindow>
#include "ui_safeboxmanager.h"
class SafeboxManager : public QMainWindow
{
Q_OBJECT
public:
SafeboxManager(QWidget *parent = 0);
~SafeboxManager();
public slots:
void init();
private:
Ui::SafeboxManagerClass ui;
LoginManager* m_LoginManager;
};
#endif // SAFEBOXMANAGER_H
mainwindow.cpp
#include "safeboxmanager.hpp"
#include "loginmanager.hpp"
SafeboxManager::SafeboxManager(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
m_LoginManager = new LoginManager();
ui.mainToolBar->setEnabled(false);
ui.tableWidget->setEnabled(false);
connect(m_LoginManager, SIGNAL(login()), this, SLOT(init()));
//m_LoginManager->setLogin() << this work
}
SafeboxManager::~SafeboxManager()
{
}
void SafeboxManager::init()
{
ui.mainToolBar->setEnabled(true);
ui.tableWidget->setEnabled(true);
}
SafeboxManager and LoginManager objects must live long enough. Check life times.
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()));
I think i have some troubles getting this right: I have a QMainWindow class. In my programm I want to create other classes e.g. for input handling, computation...
Now first from my mainwindow class i want to send to my fileselector (file handler) class to open a file dialog, thus save the selected files internally. Unfortunately I am having troubles to connect the slots.
main window:
MA_FEX::MA_FEX(QWidget *parent)
: QMainWindow(parent), fileSelector(this)
{
ui.setupUi(this);
//this works:
fileSelector.openFiles(this);
//this doesn't:
connect(ui.actionOpenFiles, SIGNAL(triggered()), fileSelector, SLOT(openFiles(this)));
}
MA_FEX::~MA_FEX()
{
}
mainwindow header:
class MA_FEX : public QMainWindow
{
Q_OBJECT
public:
MA_FEX(QWidget *parent = 0);
~MA_FEX();
private:
Ui::MA_FEXClass ui;
FileSelection fileSelector;
};
file coordination class:
FileSelection::FileSelection(QObject *parent)
: QObject(parent)
{
}
FileSelection::~FileSelection()
{
}
void FileSelection::openFiles(QWidget *parent){
QStringList files = QFileDialog::getOpenFileNames(
parent,
"Select one or more files to open",
"c:",
"Images (*.csv *.txt )");
}
header:
class FileSelection : public QObject
{
Q_OBJECT
public:
FileSelection(QObject *parent);
~FileSelection();
public slots:
void openFiles(QWidget *parent);
private:
};
Am I missing something ? Executing i get Error C2664 on the connect line saying that Parameter 3 'FileSelection' cannot be converted to 'const QObject'.
Look at the declaration of the QObject::connect:
QObject::connect(const QObject * sender, const char * signal,
const QObject * receiver, const char * method,
Qt::ConnectionType type = Qt::AutoConnection);
It takes pointers, so you need to pass a pointer to fileSelector.
Another problem there is incompatible SIGNAL and SLOT. The slot specification in connect is declaration, so you cannot pass arguments as you did with this. If you use Qt 5 and C++11 you can do that by passing lambda instead of slot specification:
QObject::connect(ui.actionOpenFiles, &QAction::triggered,
[this]() { fileSelector.openFiles(this); });
For Qt 4 you need to create wrapping slot in your MA_FEX class which takes no arguments and which will invoke the slot of the fileSelector:
class MA_FEX {
...
Q_SLOT void openFileSelector() { fileSelector.openFiles(this); }
...
public:
MA_FEX(QWidget *parent) : QMainWindow(parent), fileSelector(this) {
ui.setupUi(this);
connect(ui.actionOpenFiles, SIGNAL(triggered()), SLOT(openFileSelector()));
}
...
};
How can i emit signal from another class? In my implementation shown below I've got "unresolved external symbol error" when I try to emit signal in SerialPort::open method.
Code, head file of main window:
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
std::shared_ptr<SerialPort> serialPort;
private slots:
void labelchange();
private:
Ui::MainWindow *ui;
};
and the cpp file:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
serialPort(std::shared_ptr<SerialPort>(new SerialPort))
{
ui->setupUi(this);
connect(serialPort.get(), SIGNAL(opened()),this,SLOT(labelchange()));
}
void MainWindow::labelchange()
{
ui->testinLabel->setText("signal connected to slot");
}
and the other class method when i try emit signal:
head file:
class SerialPort : public QObject
{
public:
SerialPort();
void open()
signals:
void serial_opened();
}
and cpp file:
void SerialPort::open()
{
emit serial_opened();
}
This is just normal signal emitting from a class. Not "from another" class.
You are missing the Q_OBJECT macro, QObject do not really work with out it:
class SerialPort : public QObject
{
Q_OBJECT
public:
SerialPort();
void open()
signals:
void serial_opened();
}
And you need to have the file processed by moc. (happens automatically, if the files are listed in the .pro file)
SerialPort shall contain Q_OBJECT marco like this:
class SerialPort : public QObject
{
Q_OBJECT
public:
SerialPort();
void open()
signals:
void serial_opened();
}
Also please check your .pro file and check whether you added your SerialPort.h under HEADERS section.