Bienvenue sur le forum !

Si vous souhaitez rejoindre la communauté, cliquez sur l'un de ces boutons !

Qt 5 : 5.7.1 - Qt Creator : 4.2.0 - Qt Installer : 2.0.3 - JOM : 1.1.2 - Qt Build suite : 1.7.0 - VS Qt 5 : 2.0.0

QRadioButton dans un QTableWidget

November 2010 modifié dans Année 2011
Bonjour à tous,

J'ai actuellement un QTableWidget constitué de 4 colonnes mais dont le nombre de ligne n'est pas défini.
Lorsque j'ajoute une ligne (via une fonction), je place dans la dernière colonne un QGroupeBox qui contient un QHLayout qui contient 2 QRadioButton (1 oui et 1 non).
Lorsque je clique sur "oui" ou "non" je veux pouvoir mettre à jour un tableau. Cette modification doit prendre en compte les valeurs des autres colonnes de la ligne.

Imaginez un ligne qui contient "Nom", "somme à payer", "nom personne à rembourser", "a payé : oui ou non".
Si je clique sur "oui", je vais mettre à jour un tableau qui indiquera que la personne a payée.

Il faudrait donc que j'utilise un signal/slot qui prend en paramètre toutes les valeurs (chaque colonne) de la ligne ainsi que la valeur du RadioButton. Mais je ne sais pas comment faire.
Actuellement j'utilise un QSignalMapper qui me permet de transmettre seulement le numéro de la ligne du QTableWidget.
    QGroupBox *groupBox_Remb = new QGroupBox();
QRadioButton *radioBtn_rembOui = new QRadioButton(tr("&oui"));
QRadioButton *radioBtn_rembNon = new QRadioButton(tr("&non"));
radioBtn_rembNon->setChecked(true);
QHBoxLayout *hbox_Remb = new QHBoxLayout;
hbox_Remb->addWidget(radioBtn_rembOui);
hbox_Remb->addWidget(radioBtn_rembNon);
hbox_Remb->addStretch(1);
groupBox_Remb->setLayout(hbox_Remb);
m_listeRemboursements->setCellWidget(row, 3, groupBox_Remb);

QSignalMapper *mapper_RembOui = new QSignalMapper();
connect(radioBtn_rembOui, SIGNAL(toggled(bool)), mapper_RembOui, SLOT(map()));
mapper_RembOui->setMapping(radioBtn_rembOui, row);
connect(mapper_RembOui, SIGNAL(mapped(int)), this, SLOT(effectuerRemboursement(int)));

QSignalMapper *mapper_RembNon = new QSignalMapper();
connect(radioBtn_rembNon, SIGNAL(toggled(bool)), mapper_RembNon, SLOT(map()));
mapper_RembNon->setMapping(radioBtn_rembNon, row);
connect(mapper_RembNon, SIGNAL(mapped(int)), this, SLOT(annulerRemboursement(int)));
void FenPrincipale::annulerRemboursement(int row){
QMessageBox::information(this, "titre", tr("num ligne = %1 : remboursement annulé").arg(row));
qDebug() << row;
}
Est-ce que vous auriez une idée?
Merci d'avance

Réponses

  • Je pense que ta méthode est la bonne, grâce au numéro de ligne tu peux aller récupérer toutes les infos dont tu as besoin ...
  • November 2010 modifié
    C'était ce que je me disais hier lorsque j'écrivais ce post mais le problème c'est que je n'arrive pas a trouver comment accéder aux radiobuttons qui sont bien enfouis dans le QTableWidget : QTableWidget{colonne 4 = [GroupeBox (QHLayout {radio1 et radio2} ) ] }.

    J'ai essayé le code ci-dessous mais ca ne fonctionne pas, j'obtiens l'erreur suivante :
    sources/FenPrincipale.cpp:1103: error: ‘class QWidget’ has no member named ‘radioBtn_rembOui’
    void FenPrincipale::effectuerRemboursement(int row){
    if(m_listeRemboursements->cellWidget(row,4)->radioBtn_rembOui->isChecked())
    {
    QMessageBox::information(this, "titre", tr("num ligne = %1: remboursement effectué").arg(row));
    }
    else
    {
    QMessageBox::information(this, "titre", tr("num ligne = %1: non remboursement effectué").arg(row));
    }

    qDebug() << row;
    }
  • Personne a une idée??
  • Pour récupérer les fils d'un widget :
    QList<T> QObject::findChildren ( const QString & name = QString() ) const
    Pourquoi ne pas créer une nouvelle classe héritant de QTableWidgetItem ?
    Il ne te resterai plus qu'à mettre tes QRadioButton en tant qu'attributs.
    Cela t'éviterai les appels de méthodes en cascade et les casts.
  • Bonjour,

    Bon alors après quelque temps d'essai et de prise de tête je suis toujours bloqué.
    J'ai opté la solution de l'héritage d'un QTableWidgetItem mais je galère vraiment.

    J'ai appelé ma nouvelle Class QItemRadioButton. Voici les fichiers .cpp et .h :

    QItemRadioButton.cpp
    /*
    Nom du fichier : QItemRadioButton.cpp
    La classe QItemRadioButton hérites de la classe QTableWidgetItem
    */

    #include <QApplication>
    #include <QItemRadioButton.h>
    #include <QString>
    #include <QtGui>
    #include <QSignalMapper>

    // Constructeur par défaut
    QItemRadioButton::QItemRadioButton() : QTableWidgetItem()
    {
    // Déclaration des radiobuttons
    QGroupBox *groupBox_Remb = new QGroupBox();
    m_radioBtn_Oui = new QRadioButton(QObject::tr("&oui"));
    m_radioBtn_Non = new QRadioButton(QObject::tr("&non"));
    m_radioBtn_Non->setChecked(true);
    QHBoxLayout *hbox_Remb = new QHBoxLayout;
    hbox_Remb->addWidget(m_radioBtn_Oui);
    hbox_Remb->addWidget(m_radioBtn_Non);
    hbox_Remb->addStretch(1);
    groupBox_Remb->setLayout(hbox_Remb);

    // Mapper et signaux
    QSignalMapper *mapper_RembOui = new QSignalMapper();
    QObject::connect(m_radioBtn_Oui, SIGNAL(toggled(bool)), mapper_RembOui, SLOT(map()));
    mapper_RembOui->setMapping(m_radioBtn_Oui, row); // ca ne peut pas marcher car row n'est pas déclarer : je voudrais mettre à la place de row le numéro de la ligne
    QObject::connect(mapper_RembOui, SIGNAL(mapped(int)), this, SLOT(effectuerRemboursement(int)));

    QSignalMapper *mapper_RembNon = new QSignalMapper();
    QObject::connect(m_radioBtn_Non, SIGNAL(toggled(bool)), mapper_RembNon, SLOT(map()));
    mapper_RembNon->setMapping(m_radioBtn_Non, row); // ca ne peut pas marcher car row n'est pas déclarer : je voudrais mettre à la place de row le numéro de la ligne
    QObject::connect(mapper_RembNon, SIGNAL(mapped(int)), this, SLOT(annulerRemboursement(int)));
    }

    void QItemRadioButton::effectuerRemboursement(int row){
    }

    void QItemRadioButton::annulerRemboursement(int row){
    }
    QItemRadioButton.h
    /*
    Nom du fichier : QItemRadioButton.h
    La classe QItemRadioButton hérites de la classe QTableWidgetItem

    */

    #include <QApplication>
    #include <QRadioButton>
    #include <QTableWidget>
    #include <QWidget>
    #include <QGroupBox>
    #include <QTextStream>
    #include <QtGui>
    #include <QString>
    #include <QSignalMapper>

    #ifndef QITEMRADIOBUTTON_H_INCLUDED
    #define QITEMRADIOBUTTON_H_INCLUDED

    class QItemRadioButton : public QTableWidgetItem
    {
    Q_OBJECT // Macro obligatoire lorsqu'on veut créer des slots ou signaux supplémentaires.
    public:
    // Constructeur par défaut
    QItemRadioButton();

    void effectuerRemboursement(int row);
    void annulerRemboursement(int row);

    private:
    QRadioButton* m_radioBtn_Oui;
    QRadioButton* m_radioBtn_Non;

    };
    #endif // QITEMRADIOBUTTON_H_INCLUDED
    et voila le fichier FenPrincipale.cpp dans lequel je construit mon QTableWidget et dans lequel je souhaite mettre mes radioButton :
    ...
    ...
    ...
    QItemRadioButton *nouv_Item = new QItemRadioButton();
    //m_listeRemboursements est le QTableWidget.
    m_listeRemboursements->setItem(row, 3, nouv_Item);
    ...
    ...
    ...
    Bon alors il y a deux problèmes principaux :
    - Si je ne met pas la partie avec les mapper et signaux, la compilation se passe bien. Mais lors de l'exécution du programme, les deux
    RadioButton ne s'affichent pas du tout.

    - Si je rajouter la partie avec les mapper et signaux, la compilation plante :
    g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -Iheaders -I. -o QItemRadioButton.o sources/QItemRadioButton.cpp
    sources/QItemRadioButton.cpp: In constructor ‘QItemRadioButton::QItemRadioButton()’:
    sources/QItemRadioButton.cpp:31: error: no matching function for call to ‘QObject::connect(QSignalMapper*&, const char [13], QItemRadioButton* const, const char [29])’
    /usr/include/qt4/QtCore/qobject.h:198: note: candidates are: static bool QObject::connect(const QObject*, const char*, const QObject*, const char*, Qt::ConnectionType)
    /usr/include/qt4/QtCore/qobject.h:313: note: bool QObject::connect(const QObject*, const char*, const char*, Qt::ConnectionType) const
    sources/QItemRadioButton.cpp:36: error: no matching function for call to ‘QObject::connect(QSignalMapper*&, const char [13], QItemRadioButton* const, const char [27])’
    /usr/include/qt4/QtCore/qobject.h:198: note: candidates are: static bool QObject::connect(const QObject*, const char*, const QObject*, const char*, Qt::ConnectionType)
    /usr/include/qt4/QtCore/qobject.h:313: note: bool QObject::connect(const QObject*, const char*, const char*, Qt::ConnectionType) const
    sources/QItemRadioButton.cpp: At global scope:
    sources/QItemRadioButton.cpp:41: warning: unused parameter ‘row’
    sources/QItemRadioButton.cpp:44: warning: unused parameter ‘row’
    make: *** [QItemRadioButton.o] Erreur 1
    Je crois que là j'ai définitivement besoin d'un conseil/coup de main.
    Merci d'avance.
  • bonjour,

    et si tu ajoutes une variable private m_row dans ta classe dérivé QItemRadioButton, et tu y met le numéro de row au moment de la création de la ligne.
    je pense que comme ça tu peux récupérer m_row quand tu veux.
  • November 2010 modifié
    Bonne idée en effet pour récupérer le numéro de la ligne. Mais en revanche ca ne résoud pas du tout mon problème : Les radiobutton ne s'affichent pas et pour les signaux je galère.

    EDIT : HELP HELP HELP

    En fait je pense qu'il ne faut pas que je mette les signaux dans l'héritage du QTableWidgetItem car les fonctions que je dois appelé lorsque je clique sur un radioButton, doivent se trouver dans mon fichier FenPrincipale.cpp

    Donc je re-résume mon problème :
    Je veux avoir 2 radiobutton (horizontalement) dans la dernière cellule de chaque nouvelle ligne de mon QTableWidget.
    Lorsque je clique sur l'un des radioButton, je veux pouvoir lancer une fonction (qui est définie dans FenPrincipale.cpp). Cette fonction fait appelle à 1 fonction de la classe Personnage que j'ai créé.


    L'idée de de créer une class qui hérite de QTableWidgetItem est peut être pas mal, mais je n'arrive pas afficher les Radiobuttons.


    HELP HELP HELP
    MERCI MERCI MERCI
  • aurel2638 said:
    Bonjour à tous,
        QGroupBox *groupBox_Remb = new QGroupBox();
    QRadioButton *radioBtn_rembOui = new QRadioButton(tr("&oui"));
    QRadioButton *radioBtn_rembNon = new QRadioButton(tr("&non"));
    radioBtn_rembNon->setChecked(true);
    QHBoxLayout *hbox_Remb = new QHBoxLayout;
    hbox_Remb->addWidget(radioBtn_rembOui);
    hbox_Remb->addWidget(radioBtn_rembNon);
    hbox_Remb->addStretch(1);
    groupBox_Remb->setLayout(hbox_Remb);
    m_listeRemboursements->setCellWidget(row, 3, groupBox_Remb);

    QSignalMapper *mapper_RembOui = new QSignalMapper();
    connect(radioBtn_rembOui, SIGNAL(toggled(bool)), mapper_RembOui, SLOT(map()));
    mapper_RembOui->setMapping(radioBtn_rembOui, row); // remplacer row par taTableWidget->currentRow();
    connect(mapper_RembOui, SIGNAL(mapped(int)), this, SLOT(effectuerRemboursement(int)));

    QSignalMapper *mapper_RembNon = new QSignalMapper();
    connect(radioBtn_rembNon, SIGNAL(toggled(bool)), mapper_RembNon, SLOT(map()));
    mapper_RembNon->setMapping(radioBtn_rembNon, row); // remplacer row par taTableWidget->currentRow();
    connect(mapper_RembNon, SIGNAL(mapped(int)), this, SLOT(annulerRemboursement(int)));
    void FenPrincipale::annulerRemboursement(int row){
    QMessageBox::information(this, "titre", tr("num ligne = %1 : remboursement annulé").arg(row));
    qDebug() << row;
    }
    Avec moi après changer row par taTableWidget->currentRow(); ça marché
  • J'ai lu en diagonale mais pour ton besoin de base CAD savoir si c'est payé ou non, moi j'aurais plus basiquement mis une case à coche (payé) car dans ta solution, je trouve que tu surcharges visuellement ta grille...
  • Salut
    voici une solution
    Je définis tout abord une classe Choix qui contiendra un QGroupeBox qui contient un QHLayout qui contient 2 QRadioButton (1 oui et 1 non).
    cette classe va permettre de retournée le résultat du choix effectué par rapport à la sélection des radioButton. c'est à dire si c'est oui qui est sélectionné alors la valeur sera un "Oui" de type QString et "Non" dans le cas contraire.

    je definis une classe ChoixDelegate dont un objet de type Choix qui sera necessaire pour les itemsdelegates de la table
    Ensuite cette classe Choix sera nécessaire pour les itemsdelegates de la table

    d'abord la classe Choix
    fichier: choix.h


    // choix.h

    #include <QGroupBox>
    #include <QHBoxLayout>
    #include <QRadioButton>

    class Choix: public QWidget{

    Q_OBJECT
    public :

    Choix(QWidget *parent=0);
    ~Choix();
    QString value();

    public slots:
    void setValue(QString val );

    private:
    QGroupBox *group;
    QRadioButton *button_Oui,button_Non;
    QHBoxLayout HBoxLayout;
    // la valeur de retour
    QString m_value;

    }

    je vais pas m'attarder au niveau de mise en forme des composants IHM

    fichier choix.cpp


    void Choix::setValue(QString val){

    m_value=val;

    button_Oui->setChecked(m_value=="Oui");
    button_Non->setChecked(m_value=="Non");

    }
    QString Choix::value(){
    return m_value;
    }
    classe ChoixDelegate
    fichier .h

    #include "choix.h"
    #include <QItemDelegate>

    class ChoixDelegate:public QItemDelegate{
    Q_OBJECT

    public:
    ChoixDelegate(QObject *parent = 0);

    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
    const QModelIndex &index) const;

    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model,
    const QModelIndex &index) const;

    void updateEditorGeometry(QWidget *editor,
    const QStyleOptionViewItem &option, const QModelIndex &index) const;
    };

    fichier .cpp

    #include "choixdelegate.h"
    QWidget* ChoixDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const{

    Choix *editor=new Choix(parent);
    return editor;

    }

    void ChoixDelegate::setEditorData(QWidget *editor,
    const QModelIndex &index) const
    {
    QString value = index.model()->data(index, Qt::EditRole).toString();

    Choix *box = static_cast<Choix*>(editor);
    box->setValue(value);
    }

    void ChoixDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
    const QModelIndex &index) const
    {
    Choix *box = static_cast<Choix*>(editor);

    QString value = box->value();


    model->setData(index, value, Qt::EditRole);
    }

    void ChoixDelegate::updateEditorGeometry(QWidget *editor,
    const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
    {
    editor->setGeometry(option.rect);
    }

    ChoixDelegate::ChoixDelegate(QObject *parent){

    // constructeur
    }
    tu peux maintenant faire ceci
    tableWidget->setItemDelegateForColumn(3,new ChoixDelegate());
Connectez-vous ou Inscrivez-vous pour répondre.