Partage
  • Partager sur Facebook
  • Partager sur Twitter

Initialiser un Tablau dynamique dans un .h

11 octobre 2018 à 18:46:32

Hello tout le monde,

En ce moment j'essaye de faire le jeu de la vie avec  QT pour cela j'utilise QGraphicView

j'arrive  un moment ou je dois crée un tableau dynamique en deux dimension je sais bien le faire dans le int main() mais dans une classe impossible

voila le code 

.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <vector>



namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pBJouer_clicked();

private:
    Ui::MainWindow *ui;
    QGraphicsScene *scene;
    QGraphicsRectItem *rect; // ici sauf que je ne vois pas comment faire...

};

#endif // MAINWINDOW_H


.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"



MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    scene = new QGraphicsScene(this);
    ui->gVjeuDeLaVie->setScene(scene);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pBJouer_clicked()
{
    QPen blackpen(Qt::black);
    blackpen.setWidth(1);
    QBrush blue(Qt::blue);
    QBrush white(Qt::white);

    rect[0][0] = scene->addRect(0,0,10,10,blackpen,blue); // message d'erreur biensur
    rect[0][1] = scene->addRect(100,100,10,10,blackpen,blue);
  
}




Merci d'avance :)

-
Edité par Flemmix 11 octobre 2018 à 19:16:52

  • Partager sur Facebook
  • Partager sur Twitter
11 octobre 2018 à 19:22:03

Dans une classe, qui initialise les variables membre ?

Le constructeur et personne d'autre !

  • Partager sur Facebook
  • Partager sur Twitter
12 octobre 2018 à 0:49:09

Merci pour l'explication je me suis donc renseigner pour le constructeur j'ai vu que l'initialisation des vecteurs  ce faisait automatiquement contrairement au variable int, double etc...

j'ai donc  dans  le .h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <vector>



namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:


    void on_pBJouer_clicked();

private:
    Ui::MainWindow *ui;
    QGraphicsScene *scene;
    std::vector<QGraphicsRectItem> rect;

};

#endif // MAINWINDOW_H

et le cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "vector"



MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    scene = new QGraphicsScene(this);
    ui->gVjeuDeLaVie->setScene(scene);


}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pBJouer_clicked()
{
    QPen blackpen(Qt::black);
    blackpen.setWidth(1);
    QBrush blue(Qt::blue);
    QBrush white(Qt::white);

    rect.push_back(scene->addRect(100,100,10,10,blackpen,blue));


}

Mais  il y a toujours 2 message d'erreur que je n'arrive pas a corrige  

 no matching member function for call to 'push_back'

et

erreur : C2664: 'void std::vector<QGraphicsRectItem,std::allocator<_Ty>>::push_back(_Ty &&)': cannot convert argument 1 from 'QGraphicsRectItem *' to 'const QGraphicsRectItem &'with[    _Ty=QGraphicsRectItem]

Merci :) 



  • Partager sur Facebook
  • Partager sur Twitter
12 octobre 2018 à 0:55:30

Et on pourrait même aller plus loin, un tableau 2D est en soi un objet complexe, il devrait donc se présenter sous la forme d'une classe et donc disposer de tous les constructeurs qui vont bien. Si on a en plus quelques notions de maths (niveau collège), on va pouvoir bâtir une construction qui s'appuiera sur std::vector et qui fera parfaitement le boulot et là la magie opère, non seulement, j'ai un truc simple à manipuler, mais en plus, il sera toujours parfaitement initialisé...

addRect renvoie probablement un pointeur(j'ai la flemme d'aller regarder la doc, mais toi, tu ne devrais pas l'avoir, moi je m'en fous car ce n'est pas mon projet, toi par contre...)...

-
Edité par int21h 12 octobre 2018 à 1:01:58

  • Partager sur Facebook
  • Partager sur Twitter
Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
12 octobre 2018 à 1:02:30

Merci pour ton intervention 

Je dois  t'avouer que je n'est pas tout compris..

Surtout comment je dois procéder

A tu un lien présentant ce que tu m'explique ?  :)

Edit:  j'ai reussi donc j'ai remplacer 

std::vector<QGraphicsRectItem> rect;

par

std::vector<QGraphicsRectItem*> rect;

et dans le cpp tout fonctionne 

rect.push_back(scene->addRect(100,100,10,10,blackpen,blue));
    rect.push_back(scene->addRect(0,0,10,10,blackpen,blue));
    delete rect[1];
    rect.push_back(scene->addRect(110,110,10,10,blackpen,blue));

Si quelq'un peut m'expliquer pourquoi on doit metre * devant QGraphicsRectItem ? :)



-
Edité par Flemmix 12 octobre 2018 à 2:10:26

  • Partager sur Facebook
  • Partager sur Twitter
12 octobre 2018 à 18:16:41

Si on considère un tableau 2D, on peut le voir sous forme d'un tableau 1D, qui contient les lignes du tableau 2D mise les unes derrière les autres. C'est là qu'interviennent les maths de niveau collège la position x,y dans le tableau 2d correspond à la position x * nombres de colonne +y dans le tableau 1D. La fonction inverse est également triviale, je te la laisse en exercice, elle est basée sur la division euclidienne censée être apprise en primaire.

Avec ceci, on va encapsuler un vector dont la taille sera nombre de lignes * nombre de colonnes,  et faire les deux surcharges de l'opérateur () qui vont bien.

template<T> 
class Matrix
{
   using storage = std::vector<T>;

public:

   using size_type = typename storage::size_type;

   Matrix(size_type l,size_type c)
     :storage_(l*c,T{})
     ,lines_{l}
     ,cols_{c}
   {}

   T const & operator()(size_type x,size_type y) const
   {
      return storage_[get(x,y)};
   }
     
   T & operator()(size_type x,size_type y)
   {
      return storage_[get(x,y)];
   }
   
   size_type lines() const {return lines_;}
   size_type columns() const {return cols_;}

   
private:

   size_type get(size_type x,size_type y) const
   {
      assert(x < lines_);
      assert(y < cols_);
      return x * cols_ + y;
   }

   storage storage_;
   size_type lines_;
   size_type cols_;

};

et pour voir comment ça marche

int main()
{
   Matrix<int> m{5,5};

   for (auto i = 0 ; i < 5 ; ++i){
      for(auto j = 0; j < 5 ; ++j){
        m(i,j) = i + j; // affectation
      }
   }

   for (auto i = 0 ; i < 5 ; ++i){
      for(auto j = 0; j < 5 ; ++j){
        std::cout << m(i,j) << " "; // lecture
      }
      std::cout << "\n";
   }


}

Bien sûr, la chose peut être enrichie de constructeurs supplémentaires, pour avoir une initialisation un peu plus "pêchue".


-
Edité par int21h 12 octobre 2018 à 18:21:57

  • Partager sur Facebook
  • Partager sur Twitter
Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
12 octobre 2018 à 18:20:13

rect.push_back(scene->addRect(0,0,10,10,blackpen,blue));
delete rect[1];

 Avec ce code , tu aura toujours le pointeur dans ton vecteur qui pointe sur un element deleted .. 

  • Partager sur Facebook
  • Partager sur Twitter
14 octobre 2018 à 5:06:39

Merci pour vos réponses j'en est pris note :)
  • Partager sur Facebook
  • Partager sur Twitter