QObject::connect(): Utilizzarlo su QPushButton creati a runtime



  • Buongiorno a tutti.
    Sono arenato da un po' di tempo in un problema che non riesco a risolvere.

    Leggo da un database un certo numero di utenti.
    Per ogni utente creo un pulsante, lo visualizzo e creo il collegamento ad un evento.
    Ed è proprio sull'ultimo punto (il connect) che mi areno.

    win_main.cpp

    int rec_num = 5;   // Nel caso in cui la tabella contenga 5 record/utenti
    PushButton_T1 but_user[rec_num];
    for(int i=0; i<rec_num; i++)
    {
        str_user record;
        record = users_list->at(i);
        but_user[i] = new PushButton_T1;
        but_user[i]->setText(record.description);
        QPixmap pix = record.pix.scaled(30, 30, Qt::KeepAspectRatio, Qt::SmoothTransformation);
        but_user[i]->setPixmap(pix);
        but_user[i]->setMinimumSize(200,40);
        but_user[i]->setMaximumSize(200,40);
        ui->lay_main_left->addWidget(but_user[i]);
        QObject::connect(but_user[i], SIGNAL(clicked(bool)), this, SLOT(on_act_set_button_select(i)));
        //QObject::connect(but_user[i], SIGNAL(clicked(bool)), SLOT(Win_Main::set_button_select(i)));
    }
    
    ...
    
    void Win_Main::on_act_set_button_select(int _but_num)
    {
        QString enable;
        QString disable;
        enable.append("background-color:red;");
        enable.append("foreground-color:yellow;");
        disable.clear();
        for(int i=0; i<users_list->size(); i++)
        {
            if(_but_num==i)
            {
                but_user[i]->setStyleSheet(enable);
            } else {
                but_user[i]->setStyleSheet(disable);
            }
        }
    }
    

    win_main.h

    ...
    private slots:
        void slot_set_button_select(int _but_num);
    

    Ciò che non riesco a fare e collegare il l'evento click del pulsante appena creato ad un evento da utilizzare nel programma.

    Spero di essere riuscito a spiegarmi.
    Grazie a tutti, Valerio.



  • Ciao, fa una connec normale, togliendo
    "int _but_num"
    Come crei i pulsanti metti i riferimenti in una lista.
    Quando viene generato l'evento e quindi entri nello slot
    on_act_set_button_select()
    Per sapere qual è il pulsante che ha generato l'evento ricorda che la funzione sender() ritorna appunto l'oggetto che ha generato l'evento. Scorri quindi la lista e ne deduci chi è stato. Se vuoi puoi fare un cast senza usare la lista.... Puoi fare come preferisci.

    Ciao ciao.



    • Assegnare una non-costante come dimensione dell'array e' valido in C ma non in C++
    • L'array e' di tipo PushButton_T1 ma gli assegni PushButton_T1* quindi non puo' funzionare
    • Non puoi passare argomenti fissi quando usi SIGNAL/SLOT devi usare il nuovo connect: QObject::connect(but_user[i],&PushButton_T1::clicked,this,std::bind(&Win_Main::set_button_select,this,i));


  • Per prima cosa: Grazie ad entrambi.
    Mi rendo conto di avere lacune enormi.

    Rigiriamo la frittata...
    Se io ho un elenco di utenti inseriti in una tabella di un database, quindi a priori non so quanti utenti dovrò visualizzare a monitor.
    All'avvio del programma leggo i dati di ogni utente e per ognuno creo un pulsante all'interno di una tabella.
    Avrò quindi una tabella composta da una sola colonna con un pulsante per ogni riga.
    Li metterei all'interno di una tabella in modo da avere una scrollbar verticale in caso il numero degli utenti/pulsanti/righe superi la dimensione della finestra principale del programma.
    Ovviamente dovrò collegare uno slot all'evento click() dei vari pulsanti.

    Come concetto è corretto oppure ci sono strade alternative?



  • Riferendomi a quanto ho scritto nel post precedente ho provato a scrivere quanto segue:
    file.h

    ...
    private slots:
       void slot_set_button_select();
    ...
    
    private:
    PushButton_T1 *but_user;
    ...
    

    file.cpp

    // Creo il modello per la tabella
       QStandardItemModel *model = new QStandardItemModel(0, 1, this);
       // Imposto il modello per la tabella
       ui->tableView->setModel(model);
       // Nascondo l'intestazione e la colonna sinistra
       ui->tableView->horizontalHeader()->hide();
       ui->tableView->verticalHeader()->hide();
       // Imposto l'altezza delle righe della tabella
       QHeaderView *verticalHeader = ui->tableView->verticalHeader();
       verticalHeader->setSectionResizeMode(QHeaderView::Fixed);
       verticalHeader->setDefaultSectionSize(52);
       // Imposto la larghezza della colonna della tabella
       ui->tableView->setColumnWidth(0, 202);
       // Per ogni record della tabella del database
       // Aggiungo una riga alla tabella
       for(int i=0; i<rec_num; i++)
       {
          // Leggo i dati della tabella "users"
          str_user record;
          record = users_list->at(i);
          // Aggiungo una riga alla tabella
          model->appendRow(new QStandardItem(QString("")));
          // Creo il pulsante da inserire nella cella appena creata
          but_user = new PushButton_T1(this);
          but_user->setObjectName("but_user_"+QString::number(i));
          // Testo del pulsante
          but_user->setText(record.description);
          // Immagine del pulsante
          QPixmap pix = record.pix.scaled(30, 30, Qt::KeepAspectRatio, Qt::SmoothTransformation);
          but_user->setPixmap(pix);
          // Dimensione del pulsante
          but_user->setMinimumSize(200,50);
          but_user->setMaximumSize(200,50);
          // Aggiungo il pulsante nella cella
          ui->tableView->setIndexWidget(model->index(i,0), but_user);
          // Creo una connessione per il pulsante
          connect(but_user, SIGNAL(clicked()), this, SLOT(slot_set_button_select()));
       }
    

    Fino a quì i pulsanti ci sono e anche il "connect" fa il suo lavoro.
    Arrivato a questo punto però non ho idea di come riferirmi ai button appena creati.
    Se per esempio voglio cambiare il colore di sfondo di un pulsante quando lo premo non so da dove iniziare.
    file.cpp

    void Win_Main::slot_set_button_select()
    {
       QString enable;
       QString disable;
       // Colore del pulsante selezionato
       enable.append("background-color:red;");
       enable.append("foreground-color:yellow;");
       // Colore dei pulsanti non selezionati
       disable.clear();
       // Definisco quale button è stato premuto
       QObject* obj = sender();
       if(obj->objectName()=="but_user_0")
       {
          lbl_sbr_messages->setText("Button: 0");
          // A questo punto come faccio ad assegnare lo stile al button "but_user_0"?
        }
    }
    

    Grazie per l'aiuto
    Valerio



  • Premesso che disapprovo il codice sopra. Quello che stai facendo dovrebbe essere fatto via QStyledItemDelegate e non setIndexWidget

    if(obj->objectName().leftRef(9).compare("but_user")==0)
       {
    PushButton_T1* senderButton = qobject_cast<PushButton_T1*>(obj);
    }
    


  • Provo a vedere se ho capito...
    Utilizzando QStyledItemDelegate creo una struttura dati/modello/visualizzazione. E' corretto?
    Quindi devo creare una classe apposita per il modello che gestisca i contenuti?

    Grazie.



    • Il modello contiene i dati per ogni cella
    • la view decide come le singole celle vengono disposte (a tabella, ad albero, a cerchio)
    • il delegate si prende cura di rappresentare a schermo una singola cella

    Posso chiedere cosa usi il pulsante a fare? a leggere il codice sembra che tu stia tentando di reinventare ui->tableView->setSelectionMode(QAbstractItemView::MultiSelection);



  • Inizialmente volevo creare una lista tipo i contatti telefonici del cellulare.
    Un pulsante per ogni utente incolonnati in verticale.
    Successivamente ho deciso di inserirli in una tabella per avere lo scroll verticale.
    A quel punto probabilmente il pulsante non aveva più senso in quanto potevo intercettare il click delle celle ma ormai avevo iniziato con i pulsanti ed ero curioso di vedere se riuscivo a farlo funzionare.


Log in to reply
 

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