2017-09-05 11 views
0

Je souhaite autoriser l'utilisateur à dessiner des lignes sur l'image à l'aide de la souris, J'utilise la vue graphique et l'événement souris mais la position obtenue n'est pas la bonne position relative à l'image ici est la fonction d'événement de sourisqt positionner la souris par rapport à l'image dans une vue graphique

void InitializationDialog::mousePressEvent(QMouseEvent *event) { 
    if(drawing) { 
     points.append(event->pos()); 
     if(!points.isEmpty()) { 
      if(points.size()==1) { 
       QString fileName = list.at(choosed); 
       QImage image(fileName); 
       QGraphicsScene* scene = new QGraphicsScene(); 
       QGraphicsPixmapItem* item = new QGraphicsPixmapItem(QPixmap::fromImage(image)); 
       scene->addItem(item); 
       QColor color(255,0,0); 
       QBrush brush(color); 
       QPen pen(brush, 4); 
       QGraphicsLineItem* line = new QGraphicsLineItem(points.at(0).x(),points.at(0).y(),points.at(0).x()+1,points.at(0).y()+1); 
       line->setPen(pen); 
       scene->addItem(line); 

       ui->graphicsView->setScene(scene); 
       return; 
      } 
     } 
    } 
} 

qui devrait attirer un point (je le remplaçant par ligne longue d'un pixel pour ressembler à un point)

maintenant je le point rouge loin le clic de souris comme montré dans cette image enter image description here

Comment puis-je le faire exactement sur le curseur de la souris?

Edit:

J'ai fait une classe personnalisée pour la scène graphique pour obtenir le clic par rapport à lui, j'ai essayé la souris remplaçant pressé pour la vue graphique, mais la scène n'est pas la même taille que vue graphique et le point encore loin la souris cliquez

souris enfoncé remplaçant ma scène personnalisée n'a pas aidé beaucoup parce que je reçois toujours la position de 0,0 cliquant sur la scène, peu importe où je clique

nouveau code de fichiers:

tête f ile

#ifndef INITGRAPH_H 
#define INITGRAPH_H 
#include <QtGui> 
#include <QGraphicsView> 
#include <QGraphicsScene> 
#include <QPoint> 
#include <QGraphicsSceneMouseEvent> 
class InitGraph : public QGraphicsView { 
    Q_OBJECT 
public: 
    InitGraph(QWidget *parent = 0); 
    virtual ~InitGraph() {}; 
}; 

class CustomScene : public QGraphicsScene { 
    Q_OBJECT 
protected: 
    void mousePressEvent(QGraphicsSceneMouseEvent *event); 
signals: 
    void pressed(QPoint p); 
}; 
#endif // INITGRAPH_H 

le fichier source

#include "initgraph.h" 
InitGraph::InitGraph(QWidget *parent):QGraphicsView(parent) 
{ 
} 
void CustomScene::mousePressEvent(QGraphicsSceneMouseEvent *event){ 
    qDebug(QString::number(event->pos().rx()).toLatin1()); 
    QPoint p = event->pos().toPoint(); 
    emit pressed(p); 
} 
+1

Tout d'abord, je suggère de gérer le 'mousePressEvent' de la QGraphicsScene (http://doc.qt.io/qt-5/qgraphicsscene.html#mousePressEvent) ... Deuxièmement, je voudrais savoir pourquoi vous créez une nouvelle scène, un pixmap et un élément de ligne sur chaque 'mousePress' ??? Ce – Robert

+0

est une mauvaise pratique, vous avez raison, j'étais pressé n'a donc pas remarqué, je considérerai les faire une fois et de les supprimer au destructor, merci de me rappeler –

+0

je vais vérifier aussi le lien et vous laisser savoir si je J'ai eu des problèmes avec ça –

Répondre

2

Si vous voulez ajouter un QGraphicsLineItem vous devez utiliser les coordonnées du système de la scène pour cela vous devez utiliser la fonction scenePos() méthode de QGraphicsSceneMouseEvent et la méthode mapFromScene() des articles.

pour cela, il faut remplacer les méthodes mousePressEvent, mouseMoveEvent et mouseReleaseEvent de QGraphicsScene, de ce qui précède, je mis en œuvre dans la classe suivante:

class CustomScene : public QGraphicsScene 
{ 
    Q_OBJECT 
    QGraphicsLineItem *item; 
protected: 
    void mousePressEvent(QGraphicsSceneMouseEvent *event){ 

     item = new QGraphicsLineItem; 
     addItem(item); 
     const QPointF p = event->scenePos(); 

     item->setPos(p); 
    } 

    void mouseMoveEvent(QGraphicsSceneMouseEvent *event){ 
     const QPointF p =item->mapFromScene(event->scenePos()); 
     QLineF l = item->line(); 
     l.setP2(p); 
     item->setLine(l); 
    } 

    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event){ 
     const QPointF p =item->mapFromScene(event->scenePos()); 
     QLineF l = item->line(); 
     l.setP2(p); 
     item->setLine(l); 
    } 

}; 

Le code complet est sur le link suivant.

+0

Génial, ça marche, exactement scenepos au lieu de pos est la solution. Merci –

1

vous avez Puisque vous surchargez les événements de souris de dialogue de la position de la souris en coordonnées de dialogue. Il est préférable d'utiliser les événements du widget de dessin pour laisser Qt effectuer toute la conversation et ne pas filtrer les zones de dialogue.

Pour le rendre vraiment réutilisable, vous pouvez implémenter la sous-classe QGraphicsItem Drawable et traiter les événements de souris y ajoutant ou éditant des enfants.

EDIT ici est un exemple de travail pour vous qt-drawable-item-example

En bref:

void DrawableItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { 
    m_activePath = new QGraphicsPathItem(this); 
    m_activePath->setPen(QPen(Qt::GlobalColor(rand()%17+2), 2.0)); 
    m_activePath->setPath(QPainterPath(event->pos())); 
} 

void DrawableItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { 
    if(!m_activePath) { 
     QGraphicsItem::mouseMoveEvent(event); 
     return; 
    } 

    auto path = m_activePath->path(); 
    path.lineTo(event->pos()); 
    m_activePath->setPath(path); 
} 

void DrawableItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { 
    if(!m_activePath) { 
     QGraphicsItem::mouseReleaseEvent(event); 
     return; 
    } 
    m_activePath = nullptr; 
} 
+0

Je l'ai fait pour QGraphicsScene, comment puis-je l'éditer pour essayer QGraphicsItem à la place? voir l'édition de la question –

+0

@AmmarAtef s'il vous plaît vérifier la vérification de la réponse. J'ai ajouté le lien de repo là. Merci –

+0

qui est grand –

1

Vous recevez la position de clic sur InitializationDialog mais pas sur votre graphicsView, donc vous devez convertir cette position en utilisant moins de x et de y de vos graphiquesView

QGraphicsLineItem* line = new QGraphicsLineItem(
          points.at(0).x()-graphicsView->rect().x(), 
          points.at(0).y()-graphicsView->rect().y(), 
          points.at(0).x()+1, points.at(0).y()+1); 
+0

Cela ne fonctionne pas –

+0

Quelle est votre hiérarchie de vues? Peut-être avez-vous une certaine vue de défilement. Il suffit d'implémenter l'événement mouse à l'intérieur de la classe qui dessine l'image. –