Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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!


  • Lifetime Qt Champion

    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 your Dialog::Dialog() constructor, you create a new MainWindow(this) instance, and do your connect() on that? And this dialog is created from MainWindow when a button is clicked??

    You don't want to create another MainWindow instance! Do the connect() in MainWindow, after dialog has been created and before the emit.

    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.



  • @SGaist

    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() between sendData() and getData()?

    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:

    1. 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".

    2. 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 inherits QWidget::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.

    @JonB

    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 also QVector. 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 my listWidget->currentItem() is empty? I get my list of books from DB and show it in QlistWidget. 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?



  • @Pablo-J-Rogina

    Unfortunately I didn't thought about that.:( Thank you, program works now!


Log in to reply