Qt problème d'affichage sur un QGraphicsView

Le problème exposé dans ce sujet a été résolu.

Bonjour,

Je cherche depuis plusieurs jours mais sans succès, à afficher un rectangle à l’aide d’un bouton de souris. La pression sur le bouton me donne le premier point, le relâchement du bouton me donne la position du deuxième point. J’arrive à récupérer les 2 points, j’ai l’impression que le rectangle est créé mais qu’il ne s’affiche pas dans mon QGraphicsView. Depuis j’avance dans une jungle avec un machette émoussée :). Je vous mets mon code ci-dessous: le main.cpp

int main(int argc, char *argv[])
{
    QApplication application(argc, argv);
    MainWindow Fenetre;
    Fenetre.show();

    return application.exec();
}
**```
le mainwidow.h:**
```cpp
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void dessineRectangle(QPointF p1, QPointF p2);

protected:
    virtual void mousePressEvent(QMouseEvent *event);
    virtual void mouseReleaseEvent(QMouseEvent *event);

private:
    QGraphicsView m_vue;
    QGraphicsScene m_scene;
    QGraphicsRectItem m_rect;
    QPointF m_p1;
    QPointF m_p2;


};

et le mainwidow.cpp:

MainWindow::MainWindow(QWidget *parent) : QMainWindow (parent)
{
    this->resize(500,500);

    m_vue.setScene(&m_scene);
    m_scene.setSceneRect(0,0,400,400);
    m_vue.resize(500,500);
}

MainWindow::~MainWindow()
{
}

void MainWindow::dessineRectangle(QPointF p1, QPointF p2)
{
        m_scene.addRect(p1.x(),p1.y(),p2.x(), p2.y());
}

void MainWindow::mousePressEvent(QMouseEvent *event)
{
    std::cout << event->pos().x() << " " << event->pos().y() << std::endl;
    m_p1 = {m_vue.mapToScene(event->pos())};
}

void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    std::cout << event->pos().x() << " " << event->pos().y() << std::endl;
    event->accept();
    m_p2 = {m_vue.mapToScene(event->pos())};
    dessineRectangle(m_p1, m_p2);
}

Si quelqu’un à une idée? Je vous remercie pour votre aide.

+0 -0

Salut,

D’après la documentation de addRect les argument attendus sont qreal x, qreal y, qreal w, qreal h.

Je pense que tu dois donc fournir en 3e et 4e arguments qFabs(p2.x() - p1.x()), qFabs(p2.y() - p1.y()). Ce qui donnerait donc :

#include <QtMath>

// ...

void MainWindow::dessineRectangle(QPointF p1, QPointF p2)
{
        m_scene.addRect(p1.x(),p1.y(), qFabs(p2.x() - p1.x()), qFabs(p2.y() - p1.y()));
}

Je ne manipule plus Qt au quotidien mais si la solution ci-dessus n’est pas bonne, quelques pistes vite fait :

  • As-tu un QBrush de défini ?
  • Essaie d’invalider la zone de ta QGraphicsView concernée pour la forcer à être repeinte.
+2 -0

Bonjour Ge0,

Merci pour ta réponse. Oui tu as raison pour la méthode addRect. Si je veux des rectangles à la dimension souhaitée, il faut faire la soustraction comme tu l’as écrit. Mais ça ne résout pas le problème d’affichage.

Je n’ai pas définit de QBrush car si j’ai bien compris, le QBrush s’occupe de la forme et s’il n’est pas explicitement définit, mon rectangle prend les paramètres par défaut à savoir, couleur noire, épaisseur de trait de 1 px etc.

En ce qui concerne l’invalidation de zone du QGraphicsVeiw je ne suis pas certain de comprendre. Alors J’ai modifié ma méthode dessineRectangle comme ça : void MainWindow::dessineRectangle(QPointF p1, QPointF p2) { m_scene.addRect(p1.x(),p1.y(),p2.x()-p1.x(), p2.y()-p1.y()); m_vue.invalidateScene(m_scene.sceneRect()); } Est-ce que c’est à ça que tu pensais?

J’ai essayé autre chose. J’ai ajouté la méthode m_vue.show() dans la méthode dessineRectangle, ce qui donne : void MainWindow::dessineRectangle(QPointF p1, QPointF p2) { m_scene.addRect(p1.x(),p1.y(),p2.x()-p1.x(), p2.y()-p1.y()); //m_vue.invalidateScene(m_scene.sceneRect()); m_vue.show(); } En faisant ça, au relâchement du bouton de souris une deuxième fenêtre s’ouvre et les rectangles se dessinent de dessus: Capture d’écran de 2020-11-15 12-53-06.png La fenêtre de gauche, capte les événements souris et les rectangles apparaissent sur la fenêtre de droite. Ce n’est pas encore le résultat que je cherche. J’aurais voulut que le QGraphicsView soit intégré dans ma fenêtre principale MainWindow.

Je continue mes recherches mais si vous avez des pistes, n’hésitez pas :)

+0 -0

Parfait! C’était bien un problème de parent/enfant. L’erreur que j’ai faite est de croire qu’en déclarant l’attribut QGraphicsView m_vue; dans ma classe MainWindow, ce dernier deviendrait automatiquement un objet enfant de ma MainWindow. Apparemment non. Du coup j’ai remodelé le code comme suit: le main.cpp:

int main(int argc, char *argv[])
{
    QApplication application(argc, argv);
    MainWindow Fenetre;
    Fenetre.show();

    return application.exec();
}

le mainwindow.h:

#include <QMainWindow>
#include "VuePrincipale.h"

class MainWindow : public QMainWindow
{
    Q_OBJECT

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


private:
    VuePrincipale *m_vue;
};

le mainwindow.cpp:

#include "mainwindow.h"
#include "VuePrincipale.h"
#include <iostream>

MainWindow::MainWindow(QWidget *parent) : QMainWindow (parent)
{
    this->resize(500,500);
    m_vue = new VuePrincipale(this);

}

MainWindow::~MainWindow()
{
}

le VuePrincipale.h:

#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsSceneMouseEvent>


class VuePrincipale : public QGraphicsView
{

public:
    VuePrincipale(QWidget *parent = nullptr);
    virtual ~VuePrincipale();
    void dessineRectangle(QPointF p1, QPointF p2);


protected:
    virtual void mousePressEvent(QMouseEvent *event);
    virtual void mouseReleaseEvent(QMouseEvent *event);

private:
    QGraphicsScene m_scene;
    QPointF m_p1;
    QPointF m_p2;

};

le VuePrincipale.cpp:

#include "VuePrincipale.h"
#include <iostream>
#include <QMouseEvent>


VuePrincipale::VuePrincipale(QWidget *parent)
{
    this->setParent(parent);
    this->setScene(&m_scene);
    m_scene.setSceneRect(0,0,400,400);
    this->resize(500,500);
}

VuePrincipale::~VuePrincipale()
{
}

void VuePrincipale::dessineRectangle(QPointF p1, QPointF p2)
{
        m_scene.addRect(p1.x(),p1.y(),p2.x()-p1.x(), p2.y()-p1.y());
}

void VuePrincipale::mousePressEvent(QMouseEvent *event)
{
    std::cout << event->pos().x() << " " << event->pos().y() << std::endl;
    m_p1 = this->mapToScene(event->pos());
}

void VuePrincipale::mouseReleaseEvent(QMouseEvent *event)
{
    std::cout << event->pos().x() << " " << event->pos().y() << std::endl;
    m_p2 = this->mapToScene(event->pos());
    dessineRectangle(m_p1, m_p2);
}

Là ça fonctionne nickel. Merci pour ton aide Ge0.

+0 -0
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