Transfer data between classes.
-
It's not a problem to create signal/slot inside one class but I have some problem with passing the data between different classes. I know that there are a lot of topic about that but my programm still don't want to compile.:(
The task is very simple: I want to pass title(QString) that I get from DB from mainWindow to dialogWindow. So there is my code.
mainWindows.h
signals: void sendData(QString data); private slots: void on_btnOpen_clicked(); private: Ui::MainWindow *ui; Dialog *dialog;
mainWindows.cpp
void MainWindow::on_btnOpen_clicked() { dialog = new Dialog(this); emit sendData("title"); dialog->show(); }
When I press button btnOpen new window creating (dialog) and to this window
I want to pass the data (to simplify I hardcode data to string "title").dialog.h
private: Ui::Dialog *ui; MainWindow *mainw; private slots: void getData(QString data);
dialog.cpp
Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); mainw = new MainWindow(this); connect(mainw, SIGNAL(MainWindow::sendData(QString data)), this, SLOT(getData(QString data))); } void Dialog::getData(QString data) { ui->lblText->setText(data); }
I tried different ways but it still not working. Any help will be really appriciated!
-
Hi and welcome to devnet,
MainWindow
has nothing to do inside your Dialog class. Remove it from there and do the connection in the MainWindow class.Note that you are leaking Dialog objects in your
on_btnOpen_clicked
method as you re-create a new Dialog each time that method is called. -
@Xilit
What is going on here? In yourDialog::Dialog()
constructor, you create anew MainWindow(this)
instance, and do yourconnect()
on that? And this dialog is created fromMainWindow
when a button is clicked??You don't want to create another
MainWindow
instance! Do theconnect()
inMainWindow
, afterdialog
has been created and before theemit
.Having said that, are you sure you want signals & slots for this? It's OK to have a dialog provide methods which its creator can call directly. Look at all the members
QDialog
has. -
Thank you for quick reply!
I still can't get the point. I have my mainWindow form with data from DB. In this form I press Open button and I have my dialogWindow form opened. And in this form (dialogWindow) I want to have data from mainWindow. So for that in mainWindow.cpp constructor I should create
connect()
betweensendData()
andgetData()
?MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); connect(this, SIGNAL(sendData(QString data)), this, SLOT(Dialog::getData(QString data))); }
But how can I get my data in dialog class?
And about leaking. How can I avoid that in my case? I know only this way to open new window from another for now.@JonB
"Having said that, are you sure you want signals & slots for this?" I'm not sure in that I just made some search about my problem and common answer was creating sgnal and slots. -
unless your class uses the Q_OBJECT macro the signal/slot system won't register with the MOC. You don't include enough of your class definitions to know if you've done it properly.
-
@Xilit said in Transfer data between classes.:
@JonB
"Having said that, are you sure you want signals & slots for this?" I'm not sure in that I just made some search about my problem and common answer was creating sgnal and slots.Qt does indeed make extensive use of signals & slots, but it does not mean they should always be used for every situation. There are two general, conceptual rules about when to use signals/slots:
-
A signal is usually emitted when "something happens", some "event", such as input arriving or a UI item being clicked, etc. Your code just wants to set the dialog's title. Although you could do it via signals/slots, this isn't really "something happening".
-
Signals/slots are used to maintain separation of the code where the event is signalled from the code where the signal is handled (a slot). This is typically where the code raising the signal has no idea what the code implementing the slot(s) would like to do with the signal, and leaves it entirely to the slot code to decide. It is often also accompanied by the idea that there might be multiple slots which want to receive the signal and each do its own thing, or there might be no slots at all and nothing wants to react to the signal. In your case neither of these is the case, your caller simply wants the dialog (only) to set its title, that's it.
So, unless you have some bigger picture where you want to emit signals here, then to get the main window code to set the title of the dialog it creates I would ditch signals/slots and simply provide a
public
method in the dialog which the main window can directly call.dialog.h
public: void setLabelTitle(const QString& title);
dialog.cpp
void Dialog::setLabelTitle(const QString& title) { ui->lblText->setText(title); }
mainWindow.cpp
void MainWindow::on_btnOpen_clicked() { dialog = new Dialog(this); dialog->setLabelTitle("title"); dialog->show(); }
Notice, btw, that
QDialog
already inheritsQWidget::setWindowTitle(const QString &)
, and you can call that directly in the same way. It does not do it via your label, it changes the actual dialog title, which may or may not be what you want in this case. -
-
@Kent-Dorfman
Thank you for trying to help me! Yes, I have Q_OBJECT macro in both of my classes.Oh yes! Thank you, my friend! That's work for me.^^
Of course I need to deal with signals&slots but it will be in the future. But for now my problem is solved. Now I can pass not only
QString
but alsoQVector
. I've already check that:Dialog.cpp
void Dialog::setVector(const QVector<QString> &vectorInfo) { QString number, title, author, pages, year, price; for (int var = 0; var < vectorInfo.size(); ++var) { number = vectorInfo[0]; title = vectorInfo[1]; author = vectorInfo[2]; pages = vectorInfo[3]; year = vectorInfo[4]; price = vectorInfo[5]; } QString msg = number + "\n" + title + "\n" + author + "\n" + pages + "\n" + year + "\n" + price; ui->lblVector->setText(msg); }
This data I get from DB and pass from mainwindow to dialog. And that's work perfectly for me! Thank you again!
BTW is there some "carma" or pluses in this site? Can I set plus to you (maybe +100500)? Sorry for this, but I newbie on this site.
-
@Xilit said in Transfer data between classes.:
BTW is there some "carma" or pluses in this site? Can I set plus to you (maybe +100500)? Sorry for this, but I newbie on this site.
At the bottom-right of each post there is a little number with up & down arrows against it. You can click up to up-vote a post, and the author gets a notification. [At present these numbers do not always show correctly, hover over the number to see who has actually up-voted.]
If you would like to up-vote-click my post 100,500 times be my guest, that would be lovely (though it will only let you up-vote once) ;-)
-
@JonB
I don't want to create another topic so maybe ask here: how to check that mylistWidget->currentItem()
is empty? I get my list of books from DB and show it inQlistWidget
. When user select one item and press showInfo button - new dialog opens with detail information from DB. It's work perfectly. It WAS work perfectly untill I noticed one bug: when user select nothing and press showInfo button - my programm crashes. Of course I try to fix that in such way:QString uiTitle; if(ui->listWidget->currentItem()->text() == "") { QMessageBox::warning(this,"Warning","Please, select book item first!"); return; }else { QString uiTitle = ui->listWidget->currentItem()->text(); }
And in such way:
QString uiTitle; if(ui->listWidget->currentItem()->text().isEmpty()) { QMessageBox::warning(this,"Warning","Please, select book item first!"); return; }else { QString uiTitle = ui->listWidget->currentItem()->text(); }
Programm always crushes when it meets this line:
if(ui->listWidget->currentItem()->text() == "")
or
if(ui->listWidget->currentItem()->text().isEmpty())
I understand that there is some error here, and must be some way to check if user select item from list or not. In docs I found
selectedItems()
but it not exactly what I need (besides that it returns QList<QListWidgetItem *>).Also I used debugger and if it's needed I can post debuggers error here:
The inferior stopped because it received a signal from the operation system. Signal name: SIGSEGV Signal meaning: Segmentation fault
In my opinion line
if(ui->listWidget->currentItem()->text() == "")
should works perfectly, but Qt has another point of view. XD
Any ideas?
-
@Xilit said in Transfer data between classes.:
ui->listWidget->currentItem()
Have you thought that maybe that's returning NULL?
-
Unfortunately I didn't thought about that.:( Thank you, program works now!