PDA

View Full Version : QDialog signal and slots



ado130
20th January 2017, 18:49
Hi, I'm new here, and I'm trying to understood how works signal and slots.
I have:
mainwindow.h

...
signals:
void setMismatchText(const QString &text);
...

mainwindows.cpp

...
Dialog* dialog = new Dialog;

connect(this, SIGNAL(setMismatchText(QString)),
dialog, SLOT(getMismatchText(QString)));
...
this->setEnabled(false);
Dialog *dialog = new Dialog();
dialog->setModal(true);
emit setMismatchText(error);
if(dialog->exec() == QDialog::Accepted)
msgBox.setText("Accepted!");
else
msgBox.setText("Denied!");
msgBox.exec();
...

dialog.h

...
public slots:
void getMismatchText(const QString &text);
...

dialog.cpp

...
void Dialog::getMismatchText(const QString &text)
{
ui->plainTextEdit->appendPlainText(text);
}
...

In Dialog ui I have QPlayTextEdit Object (objectName - plainTextEdit).
When I emit in mainwindow.cpp, the text in Dialog won't change (or append).

Can you help me please what's wrong? Thanks!


edit:
OK, maybe I fix it.
dialog.h:

public:
void setText(const QString &text);

mainwindow.cpp

Dialog dialog;
dialog.setText(error);
dialog.exec();

But I'm not sure, if is it correct wayand still I want to know how works signals a slots.

Sorry for wrong thread, please admin, is possible to change it to "Newbie"?

anda_skoa
21st January 2017, 11:33
mainwindows.cpp

...
Dialog* dialog = new Dialog;

connect(this, SIGNAL(setMismatchText(QString)),
dialog, SLOT(getMismatchText(QString)));
...
this->setEnabled(false);
Dialog *dialog = new Dialog();
dialog->setModal(true);
emit setMismatchText(error);
if(dialog->exec() == QDialog::Accepted)
msgBox.setText("Accepted!");
else
msgBox.setText("Denied!");
msgBox.exec();
...


You create a dialog and connect to its slot.
Then you create another dialog and exec() it.

The first dialog receives the signal but is not shown.

Cheers,
_

ado130
21st January 2017, 23:37
Thanks a lot, I have not realize it.
Can I keep this thread alive - unlocked (for new questions), or is better make a new thread?

anda_skoa
22nd January 2017, 10:15
Depends on the question.

if it is related just add it here, if it is not, create a new thread.

Cheers,
_

ado130
29th January 2017, 14:15
Hi,
this works fine, when I emit signal from mainwindow to dialog, but now I need emit signal from Dialog to mainwindow. The code is almost same, I make this connect


connect(dialog, SIGNAL(setAccessLevel(quint16)),
this, SLOT(getAccessLevel(quint16)));

.. but when I call in dialog.cpp emit setAccessLevel(xyz), nothing happend.

I am not sure, if I can make connect in mainwindow.cpp (see above) and then emit signal in dialog.cpp.

Thanks!

edit: Maybe I solved it. This code is in dialog.cpp, is it correct way?


MainWindow mainWindow;
connect(this, SIGNAL(setAccessLevel(quint8)), &mainWindow, SLOT(getAccessLevel(quint8)));
emit setAccessLevel(xyz);


edit2: It's not working correctly. Correct me, I thinks, it will works if sending form opens received form. But I need open form from mainwindow and than from there send/emit signal to mainwindows (is still opened).
I want to do login form. After start the program opens login form and after I successfully login emits a signal with quint8 (access level) and the program will continue.

d_stranz
29th January 2017, 19:51
MainWindow mainWindow;

This is almost exactly the same as the problem pointed out by anda_skoa in his first answer: you are creating a new, second instance of MainWindow in this line, which has absolutely no relationship to the MainWindow instance you are using to create and display the dialog.

You need to either:

1 - Make the connection between the dialog's signal and the MainWindow's slot -in MainWindow- at the place where you create and display the dialog.



// MainWindow.cpp
void MainWindow::showDialog()
{
// Assumes MyDialog has a signal "setAccessLevel" and MainWindow has a slot "getAccessLevel"
MyDialog dlg;
connect( &dlg, SIGNAL(setAccessLevel(quint16)), this, SLOT(getAccessLevel(quint16)));

dlg.exec();
}


or

2 - Pass the pointer to the MainWindow instance to MyDialog and make the connection there:



// MainWindow.cpp
void MainWindow::showDialog()
{
MyDialog dlg( this );
dlg.exec();
}

// MyDialog.cpp
#include "MainWindow.h"

MyDialog::MyDialog( MainWindow * pMain, QWidget * pParent /*= 0*/ )
: QDialog( pParent )
{
// Assumes MyDialog has a signal "setAccessLevel" and MainWindow has a slot "getAccessLevel"
connect( this, SIGNAL(setAccessLevel(quint16)), pMain, SLOT(getAccessLevel(quint16)));
}


My personal preference is to do it the first way. MainWindow needs to know about MyDialog because it has to create it and show it, so it might as well connect to its signals. On the other hand, MyDialog doesn't need to know anything about who is creating and showing it. Its job is to simply tell anyone who is listening to its signals when something changes.

ado130
30th January 2017, 19:45
Yeah, I got it. It works and I agree with you, the first solutions looks better.
Thanks again!

edit: One more question. This is fine solution if I make new form. But what if form exist?
e.g.: After successfully loggin I save access level in private variable in MainWindow, but now in Settings tab I need this variable. What should I do? I'm trying make public function, sth like "quint8 getAccess(){return _access;}", but if I understand you helps, I can't do "MainWindow *mainWindow;" (or without pointer).

anda_skoa
31st January 2017, 09:04
There a multiple ways of getting access to data from different classes.

A data object both classes have access to, for example, or one class passing data to the other, or, as you said, one class being accessible to the other and having a getter function.

This is really not related to Qt at all, but basic C++.

Cheers,
_