une class par onglet

a marqué ce sujet comme résolu.

Bonjour,

Je développe un logiciel en C++ avec Qt en utilisant qt designer et j’aimerai séparer mon code avec une Class par onglet. Comment je dois faire pour accéder aux widgets de la fenêtre principal depuis une autre Class qui utilise ui ?

Merci d’avance pour votre aide.

Salut,

Dans les versions les plus récentes de Qt, toute la partie librairie Widgets du framework est dépréciée, avec pour objectif de la remplacer par Qt QML, un pseudo-langage de structuration made-in-qt pour améliorer et simplifier la structuration de tes interfaces. Bref, je te conseille de regarder de ce côté.

je ne suis pas sûr de comprendre ce que tu veux dire, mais si c’est le cas alors ton problème vient d’une erreur de conception. Il y aurait des moyens de bidouiller pour faire ce que tu demandes mais à priori le mieux serait de reprendre ton programme pour ne pas avoir à le faire car ça impliquerait de trop forte dépendance.

QtWidgets n’est pas "déprécié" pour le moment. "déprécié" signifie qu’il ne faut plus utiliser parce que ca va etre viré dans les prochaines versions. Il n’est pas prévu que QtWidgets soit supprimé dans un futur proche.

(Mais c’est bien d’utiliser le QML)

Pas sur qu’il y a un problème de conception, c’est classique pour les UI d’avoir des dépendances entre les "fenêtres". @sdz43 Pour éviter le couplage, les signaux-slots sont probablement une bonne approche dans ce cas. Par contre, pas sur que tu puisses le faire avec le QtDesigner.

+0 -0

Pas sur qu’il y a un problème de conception, c’est classique pour les UI d’avoir des dépendances entre les "fenêtres". @sdz43 Pour éviter le couplage, les signaux-slots sont probablement une bonne approche dans ce cas. Par contre, pas sur que tu puisses le faire avec le QtDesigner.

gbdivers

Oui mais pas au même niveau, c’est au conteneur de faire les liens.
Style, un widget manipule des valeurs avec un slider et un autre widget peut changer de couleur avec une valeur, je veux que la valeur du slider du 1er widget change la couleur du second, je fais un connect sur valueChanged à changerCouleur. Mais ce connect c’est MainWindow qui contient ces 2 widgets qui le fait, car il les connait les deux. Aucun des 2 n’a à connaitre l’autre, elle réalise des fonctions indépendantes

Ca, on est d’accord.

De ce que j’ai compris, il a une MainWindow qui contient des widgets qui interagissent entre eux. Pour le moment, ces widgets sont dans la même classe (la MainWindow), et il veut les séparer dans différentes classes. Du coup, les signaux-slots correspondent a ce qu’il veut faire. (Si j’ai bien compris).

+0 -0

Bonsoir, Salut,

Dans les versions les plus récentes de Qt, toute la partie librairie Widgets du framework est dépréciée, avec pour objectif de la remplacer par Qt QML, un pseudo-langage de structuration made-in-qt pour améliorer et simplifier la structuration de tes interfaces. Bref, je te conseille de regarder de ce côté.

Oui mais maintenant que j’ai avancé avec qt design, c’est un peu beaucoup de devoir recommencé depuis le début avec qml non ?

je ne suis pas sûr de comprendre ce que tu veux dire, mais si c’est le cas alors ton problème vient d’une erreur de conception. Il y aurait des moyens de bidouiller pour faire ce que tu demandes mais à priori le mieux serait de reprendre ton programme pour ne pas avoir à le faire car ça impliquerait de trop forte dépendance.

c’est un logiciel de gestion, j’utilise QTabWidget, chaque onglet contiens une catégorie (stock,achat,vente…etc) tous est accessible depuis les onglets sans ouvrir une nouvel fenêtre (ou le moins possible ) pour une question de simplicité.

En voyant le code s’entasser je me suis dit que ça serai mieux si chaque class s’occuper d’une seule catégorie, le code serai plus maintenable a l’avenir,par exemple la Class stock s’occuper que des opération concernant le stock.

De ce que j’ai compris, il a une MainWindow qui contient des widgets qui interagissent entre eux. Pour le moment, ces widgets sont dans la même classe (la MainWindow), et il veut les séparer dans différentes classes. Du coup, les signaux-slots correspondent a ce qu’il veut faire. (Si j’ai bien compris).

est ce que les signaux-slots me permette d’interagir (->text(),->setText .. etc) avec les formulaires depuis une autre class ?

merci.

Oui mais maintenant que j’ai avancé avec qt design, c’est un peu beaucoup de devoir recommencé depuis le début avec qml non ?

sdz43

Tout dépend, si le logiciel est un nouveau développement il vaut mieux, si par contre le logiciel a de la maturité et un code conséquent, c’est en effet plus compliqué de prendre cette décision (mais pas impossible, c’est ce que fait mon équipe en ce moment même sur un logiciel d’une taille respectable). ça ne devrait pas être trop dur si tu as bien pensé ton architecture en terme de donnée et représentation (Model/View, etc…)
La façon de coder est tout de même bien différente entre le qml et les widgets, tu vas donc avoir des changements majeurs si tu le réalise.

est ce que les signaux-slots me permette d’interagir (->text(),->setText .. etc) avec les formulaires depuis une autre class ?

sdz43

Oui c’est fait exprès (à part que ->text() dans ton exemple n’est ni un signal ni un slot). Je t’invite à lire la documentation de Qt pour vérifier ce que t’autorise chaque objet

Bon bin j’ai pris le temps de teste le signal et slot, ça semble pas fonctionné comme je le souhaite, même si j’arrive a connecté les deux class entre elle le slot ne modifie pas les widget de la class principal et récupérer une chaine vide "" si je tente de récupérée le contenu du widget sans afficher d’erreur. Donc j’ai vais abandonnée l’idée c’est peut être pas très faisable ou compliqué a faire. merci d’avoir pris le temps de répondre.

d’accord

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "gestion.h"

using namespace std;

Gestion::Gestion(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Gestion)
{
 setupUi(this);

}
void Gestion::on_stockAddProduct_clicked()
{
    int countrow = Gestion::model->rowCount();  
    Gestion::model->insertRows(countrow, 1);

    data = getDataForm("stock");
    int countdata = data.count();

    for(int i=0;i<countdata;i++)
    {
        Gestion::model->setData(Gestion::model->index(countrow, i+1), data[i]);
    }

    Gestion::model->submitAll();

    productTable->setModel(Gestion::model);


}
QVariantList Gestion::getDataForm(QString table)
{
    data.clear();
    if(table =="stock")
    {
        data << findChild<QLineEdit*>(table+"Name")->text()
             << findChild<QLineEdit*>(table+"Codebarre")->text()
             << findChild<QLineEdit*>(table+"Lots")->text()
             << findChild<QSpinBox*>(table+"Quantite")->text()
    }
    return data;
}

j’aimerai par exemple déplacé la function stockAddProduct et getDataForm sur autre une class qui gère seulement le stock

+0 -0

Moi je verrai un truc qui ressemble à ça

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class StockGui
{
public:
  StockGui(QWidget *parent = 0);
  ~StockGui(){}

signals: 
  void stockAdded(QVariantList);

private:
  QVariantList getDataForm();
}

StockGui::StockGui(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::StockGui)
{
 setupUi(this);

 connect(ui->m_buttonAdd, &QPushButton::clicked, this, [this](){emit this->stockAdded(this->getDataForm);});
}

QVariantList StockGui::getDataForm()
{
    QVariantList retval;
    retval << ui->m_nameEdit->text()
           << ui->m_codeBarreEdit->text()
           << ui->m_lotEdit->text()
           << ui->m_quantiteBox->value()
    return retval;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include "gestion.h"

using namespace std;

Gestion::Gestion(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Gestion)
{
 setupUi(this);

 connect(ui->m_stock, &StockGui::stockAdded, this, &Gestion::onStockProductAdded);
}
void Gestion::onStockProductAdded(QVariantList data)
{
    int countrow = Gestion::model->rowCount();  
    Gestion::model->insertRows(countrow, 1);

    int countdata = data.count();

    for(int i=0;i<countdata;i++)
    {
        Gestion::model->setData(Gestion::model->index(countrow, i+1), data[i]);
    }

    Gestion::model->submitAll();

    productTable->setModel(Gestion::model);
}

Bien sûr pour pouvoir écrire ça, j’ai fait des supposition sur le code que tu ne nous montre pas.
Et je me suis débarrassé des findChild tout moche. Il faudrait aussi probablement se passer de la QVariantList avec une structure ou quelque chose du style.

ok mais ton code c’est deux fenetre new Ui::Gestion et new Ui::StockGui alors que mois j’utilise une seul fentre avec qTabWidget. productTable c’est un qTableView qui devrais ce trouvé dans StockGui dans ton code comment faire pour appliqué un setModel dans la class Gestion.

Bien sûr pour pouvoir écrire ça, j’ai fait des supposition sur le code que tu ne nous montre pas.

qu’est ce qu’il manque comme information,j’ai fait exprès de raccourcir le code pour qu’il reste lisible.

Et je me suis débarrassé des findChild tout moche

oui c’est juste pour pas que je repéte le même code a chaque fois, c’est l’équivalent des variable dynamique en php,par contre c’est moche oui :)

Il faudrait aussi probablement se passer de la QVariantList

pourquoi ?

+0 -0

ok mais ton code c’est deux fenetre new Ui::Gestion et new Ui::StockGui alors que mois j’utilise une seul fentre avec qTabWidget.

sdz43

Avoir 2 UI ne veut pas dire avoir 2 fenêtres, dans le code que j’ai présenter, je pensais à inclure StockGui dans Gestion. StockGui est le contenu d’un des onglets du QTabWidget. Tu peut le faire dans le designer, tu drag’n’drop un QWidget dans l’onglet puis clic droit dessus > promouvoir en … et tu rentres les infos dont il a besoin (fichier d’en-tête, nom de classe etc…)

productTable c’est un qTableView qui devrais ce trouvé dans StockGui dans ton code comment faire pour appliqué un setModel dans la class Gestion.

sdz43

ok j’avais pas saisi, bah avec une simple méthode publique.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 class StockGui
 {
 public:
   StockGui(QWidget *parent = 0);
   ~StockGui(){}

   void setProductTableModel(QAbstractItemModel * models) {ui->productTable->setModel(models);}

 signals: 
   void stockAdded(QVariantList);

 private:
   QVariantList getDataForm();
 }

 StockGui::StockGui(QWidget *parent) :
     QWidget(parent),
     ui(new Ui::StockGui)
 {
  setupUi(this);

  connect(ui->m_buttonAdd, &QPushButton::clicked, this, [this](){emit this->stockAdded(this->getDataForm);});
 }

 QVariantList StockGui::getDataForm()
 {
     QVariantList retval;
     retval << ui->m_nameEdit->text()
            << ui->m_codeBarreEdit->text()
            << ui->m_lotEdit->text()
            << ui->m_quantiteBox->value()
     return retval;
 }
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 #include "gestion.h"

 using namespace std;

 Gestion::Gestion(QWidget *parent) :
     QWidget(parent),
     ui(new Ui::Gestion)
 {
  setupUi(this);

  connect(ui->m_stock, &StockGui::stockAdded, this, &Gestion::onStockProductAdded);
  ui->m_stock->setProductTableModel(Gestion::model);
 }
 void Gestion::onStockProductAdded(QVariantList data)
 {
     int countrow = Gestion::model->rowCount();  
     Gestion::model->insertRows(countrow, 1);

     int countdata = data.count();

     for(int i=0;i<countdata;i++)
     {
         Gestion::model->setData(Gestion::model->index(countrow, i+1), data[i]);
     }

     Gestion::model->submitAll();
 }

Bien sûr pour pouvoir écrire ça, j’ai fait des supposition sur le code que tu ne nous montre pas.

qu’est ce qu’il manque comme information,j’ai fait exprès de raccourcir le code pour qu’il reste lisible.

sdz43

La definition de la classe (.h) et l’UI (un screenshot plutôt que le xml illisible). En fait je disais surtout pour le positionnement des éléments, typiquement j’avais pas saisi que productTable était dans StockGui, et je savais pas si le bouton de validation faisait parti de StockGui ou de Gestion

Et je me suis débarrassé des findChild tout moche

oui c’est juste pour pas que je repéte le même code a chaque fois, c’est l’équivalent des variable dynamique en php,par contre c’est moche oui :)

sdz43

Tu peut peut-être utiliser l’héritage et le polymorphisme pour definir la base commune à cet ensemble.

Il faudrait aussi probablement se passer de la QVariantList

pourquoi ?

sdz43

Parce que c’est moche aussi, tu te prive des assurances que te confère le typage du C++ et tu perd en performance.

Bonjour,

clic droit dessus > promouvoir en

j’ai essayé de promouvoir qTableview, voila les erreur qu’il affiche :

1
2
3
4
5
6
'class Model' has no member named 'setHorizontalScrollBarPolicy'
'class Model' has no member named 'setDragEnabled'
'class Model' has no member named 'setAlternatingRowColors'
.... etc

`

une simple méthode publique.

1
void setProductTableModel(QAbstractItemModel * models) {ui->productTable->setModel(models);}

oui donc tu peu juste déplacé la partie model du code,pas les opération faite sur le widget,moi je voulez déplacé la fonction entier

Tu peut peut-être utiliser l’héritage et le polymorphisme pour definir la base commune à cet ensemble.

En faite ils y’a des widgets qui sont les même sur plusieurs onglets par exemple

QlineEdit stockName, QlineEdit stockCodebarre, QlineEdit stockLot ... etc

et

QlineEdit achatName, QlineEdit achatCodebarre, QlineEdit achatLot ... etc

donc je met juste le premier mot en variable ici QString table = stock ou table = achat

Parce que c’est moche aussi, tu te prive des assurances que te confère le typage du C++ et tu perd en performance.

ok je les met en structure.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte