sending QStringLists from dynamically created buttons using signals and slots



  • In my qt C++ application I create buttons dynamically based on a qstringlist I received! when I click the buttons I want to open an interface(dialo2.ui) and send another QStringList(based on that button that I click) to that interface via signals and slots.

    In the newly created interface the contents of the qstringlIst sent is displayed in labels!

    following is my code.

    Dialog.h

    #ifndef DIALOG_H
    #define DIALOG_H
    #include "QFrame"
    #include "QLabel"
    #include "QLineEdit"
    #include "QPushButton"
    #include "dialog2.h"
    
    #include <QDialog>
    
    namespace Ui {
    class Dialog;
    }
    
    class Dialog : public QDialog
    {
    Q_OBJECT
    
    public:
    Dialog2 dialog2;
    QFrame *f1;
    QPushButton *a;
    QList<QStringList> subMessageFields;
    QStringList buttonNames;
    explicit Dialog(QWidget *parent = 0);
    QStringList subMessages;
    QStringList Messages1;
    

    QStringList Messages2;

    ~Dialog();

    private slots:
    void on_pushButton_clicked();
    void receiveSubMessages(QStringList List);
    void openWindow();
    void getButtons();
    

    Dialog.cpp

    #include "dialog.h"
    #include "ui_dialog.h"
    #include "QFrame"
    #include "QLabel"
    #include "QLineEdit"
    #include "dialog2.h"
    
    Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    subMessages{"0"},
    
    ui(new Ui::Dialog)
    {
    ui->setupUi(this);
    
    }
    
    Dialog::~Dialog()
    {
    delete ui;
    }
    
    void Dialog::receiveSubMessages(QStringList List){
    
    subMessages=List;
    ui->comboBox->addItems(subMessages);
    
    for(int i=0;i<subMessages.size();i++){
        QString Name= QString::number(i);
        f1 = new QFrame();
        a= new QPushButton();
        a->setText(subMessages[i]);
        a->setObjectName("Button"+Name);
    
        ui->horizontalLayout->addWidget(a);
    
     //
    
    }
    getButtons();
    }
    
    void Dialog::getButtons(){
    
    Messages1<<"John"<<"Smith";
    Messages2<<"Hello"<<"Anne";
    
    for(int i=0;i<subMessages.size();i++){
           QPushButton *le = findChild<QPushButton*>(QString("Button%1").arg(i));
    if((le)&&(i==0)){
    connect(le, SIGNAL(clicked()), this, SLOT(openWindow()));
    connect(this,SIGNAL(sendList(QStringList)),&dialog2,SLOT(receiveList(QStringList)));
    emit sendList(Messages1);
    
             }
           else if((le)&&(i==1)){
                if(connect(le, SIGNAL(clicked()), this, SLOT(openWindow()))){
                connect(this,SIGNAL(sendList(QStringList)),&dialog2,SLOT(receiveList(QStringList)));
                 emit sendList(Messages2);
            }
    
             }
        
             }
    void Dialog::openWindow(){
    dialog2.exec();
    }
    

    Dialog2.h

    #include <QDialog>
    #include "QFrame"
    #include "QLabel"
    #include "QLineEdit"
    
    namespace Ui {
    class Dialog2;
    }
    
    class Dialog2 : public QDialog
    {
    Q_OBJECT
    
    public:
    QFrame *f1;
    QFrame *f2;
    QLabel *label;
    QLineEdit *text;
    QStringList subMessageList;
    explicit Dialog2(QWidget *parent = 0);
    ~Dialog2();
    
    private slots:
    void on_pushButton_clicked();
    void receiveList(QStringList List);
    
     void on_pushButton_2_clicked();
    

    Dialog2.cpp

    #include "dialog2.h"
    #include "ui_dialog2.h"
    
    Dialog2::Dialog2(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog2)
    {
    ui->setupUi(this);
    }
    
    Dialog2::~Dialog2()
    {
    delete ui;
    }
    
    void Dialog2::on_pushButton_clicked()
    {
    ui->label->setText(QString::number(subMessageList.size()));
    }
    
    void Dialog2::receiveList(QStringList List){
    subMessageList=List;
    for(int i=0;i<subMessageList.size();i++){
    //create dynamic widgets
    f1 = new QFrame();
    
    text= new QLineEdit(f2);
    label = new QLabel(f1);
    ui->verticalLayout->addWidget(f1);
            ui->verticalLayout_2->addWidget(f2);
    label->setText(subMessageList[i]);
    }
    }
    

    Here I have supported 2 buttons dynamically created( i=0 and i=1)
    But when I click the button which resembles i=0 I get the labels Hello, Anne , John, Smith ,John, Smith! I want only to see Hello Anne in the labels since that button only emits Messages1 qstringList! How can I achieve this?


  • Moderators

    @Kushan said in sending QStringLists from dynamically created buttons using signals and slots:

    for(int i=0;i<subMessageList.size();i++){

    Well, you're adding the complete list. If you only want to add part of it then do so.



  • @jsulm yeah but! If I click the first button ( i.e i==0). The dialog2.ui which opens up should only show "John" and "Smith" in the labels right? because I only emit QStringList "Message1"! but when I click that button both contents of Message1 and Message2 QStringLists are shown in the labels of dialog2.ui!


  • Qt Champions 2017

    @Kushan
    Hi
    Check what you actually sets. I does seems its only one text but hard to tell

    void Dialog2::receiveList(QStringList List) {
      subMessageList = List;
      for(int i = 0; i < subMessageList.size(); i++) {
        //create dynamic widgets
        f1 = new QFrame();
        text = new QLineEdit(f2);
        label = new QLabel(f1);
        ui->verticalLayout->addWidget(f1);
        ui->verticalLayout_2->addWidget(f2);
        QString text=subMessageList[i];
        qDebug() << "text is" << text;
        label->setText(text);
      }
    }
    
    


  • @mrjj So how can I set only the QStringList I want when a button is clicked?


  • Qt Champions 2017

    @Kushan
    what did this line give you ?
    qDebug() << "text is" << text;



  • @mrjj It gave
    text is "John"
    text is "Smith"
    text is "Hello"
    text is "Anne"
    text is "Hello"
    text is "Anne"


  • Qt Champions 2017

    @Kushan
    So that seems fine ?
    One string pr new QLabel(f1);



  • @mrjj yeah but how can I change my code so that only
    text is "John"
    text is "Smith"

    appears when I click 1st button. and
    text is "Hello"
    text is "Anne"
    appear when I click the button


  • Qt Champions 2017

    @Kushan

    You seems to connect multiple times to same dialog2

    for(int i=0;i<subMessages.size();i++){
    ....
    connect(this,SIGNAL(sendList(QStringList)),&dialog2,SLOT(receiveList(QStringList)));

    When you then call emit it will call that many times, so i think you mean just to call once
    out side the loop.


    connect(this,SIGNAL(sendList(QStringList)),&dialog2,SLOT(receiveList(QStringList)));
    for(int i=0;i<subMessages.size();i++){
    .....



  • @mrjj yeah thanx but the problem is if I place it outside then I can't connect the signal to a particular button right? Here I connect the signal using the value of i in the for loop


  • Qt Champions 2017

    @Kushan
    Only for the dialog2 as you dont create new dialog2 and hence get multiple
    connect to same.

    for the LE button , inside loop is correct. ( as you find new one to connect to )

    So only call
    connect(this,SIGNAL(sendList(QStringList)),&dialog2,SLOT(receiveList(QStringList)));
    ONCE or it will send many times to same dialog.



  • @mrjj Thanx alot! now it is 80% working! But the only problem I face now is when I click the 1st button close the dialog2.ui which pops up and click the second button and open dialog2.ui it is like

    text is "John"
    text is "Smith"
    text is "Hello"
    text is "Anne"

    How can I remove the following part?
    text is "John"
    text is "Smith"


  • Qt Champions 2017

    @Kushan
    If you reuse same dialog2 for button1 AND button2, it will still have the Labels from last time.
    I think most easy would be to delete it and create it again.
    (its not super easy to clear a layout)

    I assume its this one ?
    Dialog2 dialog2;

    its a bit hard to delete as its not pointer.

    you could use

    void clearLayout(QLayout *layout) 
    {
        if (layout) {
            while(layout->count() > 0){
                QLayoutItem *item = layout->takeAt(0);
                QWidget* widget = item->widget();
                if(widget)
                    delete widget;
                delete item;
            }
        }
    }
    

    void Dialog2::receiveList(QStringList List){
    clearLayout(ui->verticalLayout);
    ....

    So each time you call Dialog2::receiveList it removes what it has and then add the new stuff.



  • @mrjj Thanx when I delete the dialog2.ui and click the 2nd button nothing gets opened


  • Qt Champions 2017

    What you mean delete dialog2.ui ? ( ui files are like cpp/.h files)

    is it not the variable in Dialog called Dialog2 dialog2 u are using ?



  • @mrjj Thanx alot it works fine! I am also interested in using pointers!

    if I had used Dialog2 *dialog2 = new Dialog2(); instead of Dialog Dialog2 what should I do without using the clearLayout method?


  • Qt Champions 2017

    @Kushan
    just
    delete dialog2;
    dialog2->deletelater();
    (that also delete all you put into it)

    And BEFORE using it again
    dialog2 = new Dialog2(); // new it again

    Note:
    Qt has a auto delete system. So any parent will delete its children so
    dont delete a button u have given to a layout.
    http://doc.qt.io/qt-5/objecttrees.html
    It works here as you dont give the dialog a parent.

    if you did
    Dialog2 *dialog2 = new Dialog2(this); "this" would own it and
    it would be bad to delete it manually as when ever "this" is deleted it would
    try to delete dialog. ( a second time)

    update
    Also
    you can use
    setAttribute(Qt::WA_DeleteOnClose);
    which will auto delete dialog when you press close/ok/cancel
    and in that case , you must new it before use each time and it will
    delete itself


  • Lifetime Qt Champion

    In the case mentioned by @mrjj , use deleteLater.


  • Qt Champions 2017

    @SGaist
    doh, of course.
    Thanks



  • @SGaist Thanx mate :) Qt rox :D



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.